0% found this document useful (0 votes)
230 views

Realhowto Java 201511

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
230 views

Realhowto Java 201511

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 1149

Real's HowTo PDF version

Real's HowTo PDF version

Table of Contents
Real's HowTo PDF version (november 2015)..................................................................................................1

AWT.....................................................................................................................................................................3
java-awt....................................................................................................................................................3
Use the CardLayout manager...................................................................................................................3
Detect which card is visible with a CardLayout......................................................................................6
Use Popups..............................................................................................................................................6
Use a File Dialog.....................................................................................................................................9
Use TrueType font.................................................................................................................................10
Display available fonts...........................................................................................................................11
Font with 3D effect................................................................................................................................11
Use the System Clipboard......................................................................................................................12
Maximize a Frame.................................................................................................................................13
Center a Frame/Dialog...........................................................................................................................15
Close a Frame........................................................................................................................................16
Call events on a Frame from a Panel.....................................................................................................17
Set the small top-left icon on a Frame...................................................................................................19
Prevent a Frame to be resized................................................................................................................20
Embed an image into a Frame...............................................................................................................21
Display a message box...........................................................................................................................23
Display a Splash screen.........................................................................................................................25
Vibrate a Window..................................................................................................................................27
Limit TextField input to numeric value.................................................................................................30
Limit TextField input to a maximum length..........................................................................................31
React to the ENTER key in a Textfield.................................................................................................32
Make the ENTER key act like the TAB key..........................................................................................33
Reset all textfields in one shot...............................................................................................................34
Limit a TextField to Uppercase.............................................................................................................35
Have an ImageButton............................................................................................................................36
Reset a checkbox group.........................................................................................................................39
Set the listbox width..............................................................................................................................40
Align the column in a List.....................................................................................................................41
Have a srolling text display using a List................................................................................................41
Label dynamic resizing..........................................................................................................................42
Make a TextArea "word-wrap"..............................................................................................................44
Synchronize a TextArea versus a Choice..............................................................................................44
Display underlined text..........................................................................................................................45
Display vertical text...............................................................................................................................45
Have Label with many lines..................................................................................................................46
Have a Label with underlined text.........................................................................................................51
Have a Label acting as HTML HREF (URLLabel)...............................................................................52
Display a GIF in a Canvas.....................................................................................................................54
Embed an image into a Frame...............................................................................................................55

i
Real's HowTo PDF version

Table of Contents
AWT
Load several images from a single GIF.................................................................................................57
Load an Image from a JAR file..............................................................................................................58
Load an Image from a JAR file (again).................................................................................................59
Scale an Image.......................................................................................................................................60
Fade an image........................................................................................................................................62
Rotate an image......................................................................................................................................64
Create a scrollable canvas......................................................................................................................67
Use an Image as the Applet background................................................................................................70
Have a simple Image browser................................................................................................................72
Simulate a "mouse over" event to toggle an image...............................................................................75
Hide the mouse cursor...........................................................................................................................77
Make a color transparent........................................................................................................................77
Save an Image as a GIF or JPEG file.....................................................................................................79
Use the same background color as the browser.....................................................................................80
Do simple animation using Images........................................................................................................81
Do simple animation to show "work in progress".................................................................................82
Get the color of a specific pixel.............................................................................................................84
Do "rubber-band" drawing.....................................................................................................................85
Convert RGB value to Hex (to be used in HTML)................................................................................87
Draw a line or set a pixel in my own image..........................................................................................87
Draw dashed line....................................................................................................................................88
Draw a line with a thickness..................................................................................................................89
Draw a pie chart.....................................................................................................................................91
Draw faster rectangles............................................................................................................................94
Get a screen capture and save it as a JPEG............................................................................................95
Detect a double click versus a simple click...........................................................................................95
Detect the mouse button used when clicking.........................................................................................97
Exit an application from a menu (single exit point)..............................................................................98
Trigger a click on a Button....................................................................................................................99
Display a TIF.......................................................................................................................................100
Convert a multi-page TIF into single-page TIF...................................................................................102
Convert many single-page TIF into one multi-page TIF.....................................................................103
Convert an Image to a BufferedImage.................................................................................................104
Detect if a TIF is blank........................................................................................................................105
Convert TIF to PDF.............................................................................................................................108
Convert TIF to JPG..............................................................................................................................110

Date and Time.................................................................................................................................................112


java-date...............................................................................................................................................112
Have year on 4 digits from a Date object............................................................................................112
Get the current Date and Time.............................................................................................................112
Compute days between 2 dates............................................................................................................113

ii
Real's HowTo PDF version

Table of Contents
Date and Time
Get the number of days in a month......................................................................................................115
Validate a date......................................................................................................................................115
Determine the day of the week............................................................................................................117
Add/Substract Day/Month/Year to a Date...........................................................................................118
Get the correct TimeZone on DateFormat...........................................................................................119
Simply format a date as "YYYYMMDD"...........................................................................................120
Compare 2 dates...................................................................................................................................120
Parse a String to obtain a Date/GregorianCalendar object..................................................................121
Use System time to generate unique ID...............................................................................................122
Get the day name.................................................................................................................................122
Find the date format pattern.................................................................................................................123
Get a julian date...................................................................................................................................124
Calculate the age..................................................................................................................................127
Format a duration in milliseconds into a human-readable format.......................................................128
Get the atomic time..............................................................................................................................131
Get a date interval................................................................................................................................133
Determine if a given hour is between an interval................................................................................135
Set the computer clock (JNI)...............................................................................................................137
Get unique numerical id based on the system time..............................................................................138
Get the month (or day) name (localized).............................................................................................138
Detect a leap year.................................................................................................................................139

Environment....................................................................................................................................................141
java-env................................................................................................................................................141
Read environment variables from an application................................................................................141
Read environment variables (JDK1.5).................................................................................................145
Read environment variables (JNI).......................................................................................................146
Use a MAKE file.................................................................................................................................147
Detect the browser/JVM type..............................................................................................................148
Fix the "Wrong magic number" error message....................................................................................150
Use a precompiler "à la C" with Java..................................................................................................150
Determine what are the classes actually used......................................................................................152
Set the memory available to the JVM..................................................................................................153
Generate the Javadoc "en français"......................................................................................................153
Use JDK1.5 new features.....................................................................................................................154
Check the class version........................................................................................................................155
Get the system properties or the JVM uptime.....................................................................................156
Detect if running in a 64bit JVM.........................................................................................................157
Set the default JVM type......................................................................................................................158
Select a particular JRE from the command line...................................................................................159
Get the PID (pure Java solution)..........................................................................................................160
Get the PID (JNI solution)...................................................................................................................161

iii
Real's HowTo PDF version

Table of Contents
Environment
Set default value for Java property or JVM option (system wide)......................................................162
Detect if running in debug mode.........................................................................................................163
Configure Java deployment with properties........................................................................................163
Wrap a Java bean in a COM object (using Sun ActiveX bridge)........................................................167
Query the Windows Registry (reg.exe)...............................................................................................169
Query/Update the Windows Registry (hack).......................................................................................172
Quickly retrieve available Java JVM on a workstation (Windows)....................................................181
Detect if a Windows service is running (capture VBS return code)....................................................182
List currently running processes (Windows).......................................................................................184
Check if a program or process is running (Windows).........................................................................186
Check if a process is running (Windows) using WMIC......................................................................188
Windows registry vs Java JDK/JRE installation.................................................................................189
Get the current Java version from a BAT file......................................................................................190
Get the Windows "My Documents" path.............................................................................................192
Get the Windows Desktop path...........................................................................................................192
Get the Windows Special Folders........................................................................................................194
Create an Internet Shortcut..................................................................................................................195
Detect if running in remote session (Windows)..................................................................................197
Detect if running in a Citrix session (Windows).................................................................................198
Create a Taglet to document database access (Javadoc)......................................................................199
Generate the Javadoc "en français"......................................................................................................203
Document a package using Javadoc....................................................................................................204
Display a comment in a Javadoc..........................................................................................................205
Display XML in a Javadoc..................................................................................................................206
Add a copyright notice to a Javadoc....................................................................................................207
Use a Log file.......................................................................................................................................207
Trace the execution..............................................................................................................................210
Time the execution...............................................................................................................................212
Log information efficiently (with Log4J)............................................................................................213
Change the logging level on-the-fly (Log4J).......................................................................................214
Enable debug log level on OpenSource package(Apache Commons Logging)..................................215
Make a JAR executable.......................................................................................................................216
Application with multiples Jars...........................................................................................................218
Extract a file from a Jar........................................................................................................................218
Determine if running from JAR...........................................................................................................220
Get list of classes in package (in a Jar)................................................................................................221
Add version to Jar packaging...............................................................................................................223
Use ANT to Build a JAR with version/build number..........................................................................225
Include all jars in the classpath definition............................................................................................229
Detect browser type from an Applet....................................................................................................233
Detect if Java is enabled from HTML.................................................................................................234
See the Java Console Window Log (Java plugin)...............................................................................235

iv
Real's HowTo PDF version

Table of Contents
Internationalization........................................................................................................................................236
java-inter..............................................................................................................................................236
Load resources based upon client environment at startup...................................................................236
Load resources dynamically................................................................................................................239
Load resources via a resource file........................................................................................................243
Display "special character" using Unicode..........................................................................................247
Display chinese/japanese characters in an Applet...............................................................................248
Localize a JOptionPane dialog.............................................................................................................249
Validate/Convert a number using the current Locale()........................................................................251
Localize a JFileChooser.......................................................................................................................252
Disable localization..............................................................................................................................255
Generate the Javadoc "en français"......................................................................................................256
Sort an array with international characters..........................................................................................257
Accentuated characters in Properties/ResourceBundle file.................................................................259
Compare accentuated letters................................................................................................................259
Remove accent from letters (ex .é to e)...............................................................................................261
Output accentuated characters to the console......................................................................................265
Get the default character set of the JVM.............................................................................................266
Convert OEM (DOS) file to Ansi (Windows).....................................................................................267
Detect non-ASCII character in a String...............................................................................................268
Get the month (or day) name (localized).............................................................................................269

IO......................................................................................................................................................................271
java-io..................................................................................................................................................271
Redirect output(stdout/stderr) to a frame.............................................................................................271
Redirect printStackTrace() to a String.................................................................................................272
Redirect to NULL device.....................................................................................................................273
Print a text file using the javax.print API............................................................................................274
Print a String using the javax.print API...............................................................................................276
Print text to a printer easily..................................................................................................................278
Print without a Dialog..........................................................................................................................278
Initialize and write to a serial port.......................................................................................................279
Open or close a CD/DVD drive...........................................................................................................279
Get the volume label............................................................................................................................281
Detect the storage device type.............................................................................................................282
Turn on MQ Debug mode....................................................................................................................283
Get faster console output (System.out.println() replacement).............................................................283
Simple input from the keyboard..........................................................................................................285
Output french character to the console................................................................................................286
Clear the console and control attributes...............................................................................................288
Easy keyboard input (JDK1.5).............................................................................................................290
Force keyboard input in CAPS LOCK on...........................................................................................292
Automatic conversion of System.out output........................................................................................293

v
Real's HowTo PDF version

Table of Contents
IO
Execute an external program and capture the output...........................................................................294
Launch the application associated with a file extension......................................................................301
Launch an application from another application.................................................................................302
Start the default browser from an application......................................................................................304
Execute a Windows Shortcut (.lnk).....................................................................................................306
Create a file association with a Java program......................................................................................307
Capture the output from a VBS...........................................................................................................308
Get a return code from a VBS..............................................................................................................310
Execute a CMD file stored in a JAR....................................................................................................311
Open the default file explorer..............................................................................................................312
Read the content of a file.....................................................................................................................313
Read a text file from a Jar....................................................................................................................315
Read a text file from the internet.........................................................................................................318
Extract a file from a Jar........................................................................................................................318
Read a data file with floats...................................................................................................................320
Write to the end of a file......................................................................................................................321
Write "real" ascii file...........................................................................................................................322
Copy a file............................................................................................................................................323
Use a "log file".....................................................................................................................................326
Delete files with a certain extension....................................................................................................327
Insert a line in a file.............................................................................................................................328
Read a file into a variable in one shot..................................................................................................329
Serialize an object to a file...................................................................................................................330
Redirect stdout to a file........................................................................................................................332
Get the "last modified" date from a file...............................................................................................332
Get the file creation time......................................................................................................................332
Check if a file exists.............................................................................................................................333
Detect file (or folder) modification......................................................................................................333
File/directory polling to detect change................................................................................................337
Detect file (or folder) modification (Java 7)........................................................................................338
Get the current directory......................................................................................................................339
Get the "root" of an application...........................................................................................................340
Get the content of a directory with a Filter..........................................................................................340
Get the content of a directory with subdirectories...............................................................................343
Get directory content faster with many files........................................................................................345
Make a directory..................................................................................................................................347
Create a fixed-length file.....................................................................................................................347
Delete a non-empty directory...............................................................................................................347
Create a temporary file.........................................................................................................................348
Get the default character set of the JVM.............................................................................................349
Parse a pathname..................................................................................................................................350
Handle CSV files.................................................................................................................................350

vi
Real's HowTo PDF version

Table of Contents
IO
Convert OEM (DOS) file to Ansi (Windows).....................................................................................352
Close a stream in a try/catch block......................................................................................................353
Rename a file extension.......................................................................................................................354
Remove a file extension.......................................................................................................................356
Remove HTML tags from a file to extract only the TEXT.................................................................356
Get the Mime Type from a File...........................................................................................................359
Sort a directory listing (based on the last modified timestamp)..........................................................364
Sort files by the extension....................................................................................................................365
Filter a directory listing by date...........................................................................................................367
Convert wildcard to a regex expression...............................................................................................368
Shorten a long path..............................................................................................................................369
Force a valid Windows filename.........................................................................................................374
Check if filename is valid....................................................................................................................374
Dump a file to a HEX file....................................................................................................................375
List all files in the classpath or in a Jar................................................................................................377
Handle UTF8 file with BOM...............................................................................................................378
Touch a file..........................................................................................................................................381
Handle Excel files................................................................................................................................382
Create an Excel file (the easy way)......................................................................................................388
Detect if a XLS Excel file contains a macro (using POI)....................................................................389
Create or process PDF files..................................................................................................................390
iText - Create a PDF............................................................................................................................393
Split a PDF file (using iText)...............................................................................................................394
Concatenate PDF files (using iText)....................................................................................................395
Convert TIF to PDF.............................................................................................................................397
Convert HTML to PDF using iText.....................................................................................................399
Convert HTML to PDF using YAHP..................................................................................................401
Convert PNG/JPG/GIF to PDF using iText.........................................................................................403
Print a PDF...........................................................................................................................................404
Extract text from a PDF using Apache Tika........................................................................................405
Create a compressed (ZIP) file............................................................................................................405
Display compressed (ZIP) file content................................................................................................407
Expand the compressed (ZIP) file........................................................................................................408
Emit a beep..........................................................................................................................................409
Emit a tone...........................................................................................................................................409
Play an audio file from an application.................................................................................................411
Produce special sound effect................................................................................................................412
Use the Java Speech API (JSPAPI).....................................................................................................416
Play a Windows sound.........................................................................................................................418

vii
Real's HowTo PDF version

Table of Contents
JDBC................................................................................................................................................................420
java-jdbc...............................................................................................................................................420
Get JDBC driver for major database vendors......................................................................................420
Connect to a database via JDBC-ODBC.............................................................................................420
SELECT data from a table...................................................................................................................422
INSERT data into a table.....................................................................................................................423
MODIFY data in a table......................................................................................................................425
DELETE data in a table.......................................................................................................................425
Test for an empty ResultSet.................................................................................................................426
Get row count from SQL.....................................................................................................................426
Store and retrieve an object from a table.............................................................................................427
Retrieve an Image................................................................................................................................429
Insert an Image.....................................................................................................................................429
Call a stored procedure........................................................................................................................430
Stored procedure with Input/Output parms and a ResultSet................................................................430
Fix incomplete field returned by the ResultSet....................................................................................432
Transfer a ResultSet to a JTable..........................................................................................................432
Detect SQL error or warning...............................................................................................................432
Make DSN-less connection..................................................................................................................434
Select a CharSet when connecting to DBMS......................................................................................435
List tables in a database.......................................................................................................................435
Enable JDBC logging..........................................................................................................................437
Detect if a table exists..........................................................................................................................438
Convert a ResultSet in XML...............................................................................................................439
Display ResultSet data in an HTML Table in Servlet.........................................................................441
Escape special character in a LIKE clause..........................................................................................442
Log the SQL Statements......................................................................................................................442
Insert data in batch mode.....................................................................................................................444
Retrieve large ResultSet.......................................................................................................................446
Handle dates.........................................................................................................................................447
Get current date using JDBC...............................................................................................................449
Insert the current date...........................................................................................................................450
Read Excel worksheet..........................................................................................................................450
Handle Excel files................................................................................................................................452
Connect to an Oracle database with JDBC..........................................................................................459
Connect to Oracle using a connection pool.........................................................................................461
Retrieve the generated keys (JDBC Oracle)........................................................................................464
Debug Oracle JDBC connection..........................................................................................................465
Connect to an Oracle database using Kerberos....................................................................................467
Identify the connected program to an Oracle database........................................................................469
Use a CHAR field in the WHERE clause in a PreparedStatement......................................................470

viii
Real's HowTo PDF version

Table of Contents
JNI/JNA...........................................................................................................................................................473
java-jni.................................................................................................................................................473
Use native code through JNI (HelloWorld).........................................................................................473
Pass string to/from Java to/from C......................................................................................................473
Set the computer clock.........................................................................................................................475
Determine the signature of a method...................................................................................................476
Use arrays.............................................................................................................................................477
Load a DLL..........................................................................................................................................479
Use the MouseWheel...........................................................................................................................480
Throw an exception in JNI...................................................................................................................480
Throw my own exception in JNI.........................................................................................................481
JNI from a Package..............................................................................................................................482
Make a Window stay on top................................................................................................................482
Start JVM from C................................................................................................................................483
Retrieve environment variable (JNI)...................................................................................................484
Get the PID..........................................................................................................................................484
Clear the console, set color and cursor position (JNI).........................................................................485
Call Windows API (Open source solution).........................................................................................488
Detect if a program is running (JNA)..................................................................................................489
Close an external windows program using JNA..................................................................................490
Get Windows Special Folders (JNA)...................................................................................................492

Javascript interaction.....................................................................................................................................494
java-js...................................................................................................................................................494
* Read me *.........................................................................................................................................494
Wake-up a Java applet.........................................................................................................................494
Call a Java method from Javascript.....................................................................................................497
Call a Java method from Javascript using DOM.................................................................................499
Access Java variables from Javascript.................................................................................................499
Call Javascript from a Java applet.......................................................................................................500
Create dynamic HTML from a Java applet..........................................................................................503
Inter-Applets communication across frames.......................................................................................504
Inter-Applet communication across pages...........................................................................................506
Write HTML FORM values from a Java applet..................................................................................508
Detect if an Applet is ready.................................................................................................................509
Read/Write HTML field values from Java..........................................................................................510
Detect if Java is enabled......................................................................................................................512
Detect if Java 1.1 (with event delegation) is available........................................................................512
Access Cookies from a Java Applet.....................................................................................................513
Set Applet PARAM VALUE from Javascript.....................................................................................516
Pass an Array between Java and Javascript.........................................................................................517
Interaction without LiveConnect.........................................................................................................520
Directory listing on the Web server in a Java Applet..........................................................................525

ix
Real's HowTo PDF version

Table of Contents
Javascript interaction
Have a Java button close the browser window....................................................................................528
Detect if cookies are enabled...............................................................................................................528
Display a page after all Applets are loaded.........................................................................................529
Detect browser type from an Applet....................................................................................................530

Servlet/JSP.......................................................................................................................................................533
java-jsp.................................................................................................................................................533
Read me...............................................................................................................................................533
Get servlet parameters..........................................................................................................................533
Servlet with no args.............................................................................................................................534
Set a Cookie from a servlet..................................................................................................................535
Read a Cookie from a servlet...............................................................................................................535
Delete a Cookie from a servlet.............................................................................................................536
Ask a password from a Servlet............................................................................................................536
Talk to a Servlet/JSP from an Applet..................................................................................................537
Test for Cookies support......................................................................................................................538
Display ResultSet data in an HTML Table in Servlet.........................................................................539
Specify the filename to be used for a file sent by a Servlet.................................................................539
Pass information to another servlet/jsp................................................................................................540
Handle PDF output..............................................................................................................................540
Detect if a connection is secured.........................................................................................................541
In a Servlet, check if Form Field is present.........................................................................................541
Get the root dir of a web app...............................................................................................................541
Get Client IP from JSP.........................................................................................................................541
Binary output from a JSP.....................................................................................................................542
Use a connection cache from JSP........................................................................................................543
Read a web application property..........................................................................................................545
Use EJB from JSP................................................................................................................................545
Define a method in a JSP page............................................................................................................546
Precompile JSP page............................................................................................................................546
Get a list of directories from JSP.........................................................................................................547
Use and share a class in JSP pages......................................................................................................548
Get the root dir of a web app...............................................................................................................549
Launch an applet from a JSP...............................................................................................................550
Prevent caching of a JSP output...........................................................................................................550
Launch an external program, capture its output and display it in a JSP..............................................551
Call another EJB..................................................................................................................................553
Keep java files generated from JSP (BEA WLS)................................................................................553
Get the server version (BEA WLS).....................................................................................................553
Quickly create a Web application with BEA WLS.............................................................................554
Nicely display WEB.XML informations.............................................................................................554
Reverse the CLASSLOADER order (BEA)........................................................................................556

x
Real's HowTo PDF version

Table of Contents
Servlet/JSP
Detect change in JSP and recompile (BEA)........................................................................................557
Obtain a remote connection to a DataSource or EJB (Weblogic).......................................................557

Language..........................................................................................................................................................560
java-language.......................................................................................................................................560
*Read me*...........................................................................................................................................560
Obtain from where a Class is loaded...................................................................................................560
Get the class name in a static method..................................................................................................561
Get the current method name...............................................................................................................562
Call a method dynamically..................................................................................................................564
Detect if a package is available............................................................................................................566
Create an Object from a String............................................................................................................567
Get a variable value from the variable name.......................................................................................568
Make methods that have unspecified number of parameters...............................................................569
Create a java source dynamically, compile and call............................................................................570
Launch an application from another application.................................................................................573
Access the enclosing class from an inner class....................................................................................574
Access inner class from outside...........................................................................................................575
Use globally defined constants............................................................................................................576
Serialize an Object...............................................................................................................................577
Serialize an Object over a Socket........................................................................................................579
Easily remove my debugging code......................................................................................................579
Have a Singleton..................................................................................................................................580
Multiple expressions in for loops.........................................................................................................581
Handle the List conflict (java.awt.List/java.util.List)..........................................................................581
Use a generic toString().......................................................................................................................582
Use a Object.clone().............................................................................................................................584
Static field, constructor and exception.................................................................................................585
Use a Label break.................................................................................................................................586
Put printStackTrace() into a String......................................................................................................586
Iterate enum values..............................................................................................................................587
Get fields and values from an Object...................................................................................................588
Use a Hashtable....................................................................................................................................589
Scan the content of a hashtable............................................................................................................590
Sort an array.........................................................................................................................................590
Initialize multidimensional array.........................................................................................................592
Get array upperbound..........................................................................................................................593
Convert a String to an array or an array to a String.............................................................................593
Sort Collection in reverse order...........................................................................................................595
Resize an array.....................................................................................................................................596
Dump array content (JDK1.5)..............................................................................................................597
Initialize a static array..........................................................................................................................598

xi
Real's HowTo PDF version

Table of Contents
Language
Sort an Hashtable.................................................................................................................................599
Eliminate "[unchecked] unchecked call ..." compiler warning............................................................600
Sort on many fields..............................................................................................................................602
Optimize Collection usage...................................................................................................................605
Sort an HashMap..................................................................................................................................606
Get keys corresponding to a value from a Map...................................................................................608
Iterate a Collection and remove an item..............................................................................................609
Count distinct elements in a Vector.....................................................................................................611
Dump the content of a Collection (JDK 1.5).......................................................................................612
Initialize a Collection...........................................................................................................................614
Merge (or add) two arrays into one......................................................................................................616
Define an array (or Map, or ENUM) of functions...............................................................................617
Join a List as a String...........................................................................................................................620
Remove duplicates from a List............................................................................................................621
Convert a Map to a Properties (or vice versa).....................................................................................622
Use an INI file (properties)..................................................................................................................623
Load a properties file...........................................................................................................................625
Accentuated characters in Properties/ResourceBundle file.................................................................626
Have a multi-line value in a properties file..........................................................................................626
Use XML with Properties....................................................................................................................627
Use the Registry to store informations.................................................................................................628
Sort Properties when saving.................................................................................................................629
Resolve environment variable in a property value..............................................................................630

Networking......................................................................................................................................................633
java-net.................................................................................................................................................633
Extract network card address...............................................................................................................633
Get the workstation name/ip................................................................................................................636
Find a port number not in use..............................................................................................................638
Disable DNS caching...........................................................................................................................638
Examine the internal DNS cache.........................................................................................................639
Allow user:password in URL...............................................................................................................642
Encode/Decode to/from Base64..........................................................................................................642
Lookup using MX record to validate mail server................................................................................644
Send an email using the SMTP protocol.............................................................................................654
Check if there is mail waiting..............................................................................................................655
Receive email.......................................................................................................................................657
Send email with an attachment............................................................................................................659
Send email with JavaMail....................................................................................................................666
Send email with authentication (JavaMail)..........................................................................................668
HTML mail with images (JavaMail)...................................................................................................669
Debug a Javamail Program..................................................................................................................672

xii
Real's HowTo PDF version

Table of Contents
Networking
Send email with SMTPS (eg. Google GMail) (Javamail)...................................................................673
Mix plain text and HTML content in a mail........................................................................................675
Read an Outlook MSG file (OpenSource packages)...........................................................................676
Handle EML file with JavaMail..........................................................................................................679
Receive email (and attachment) using IMAP......................................................................................681
Receive email (and attachment) using POP3.......................................................................................684
Debug a HttpURLConnection problem...............................................................................................686
Check if a file was modified on the server..........................................................................................688
Check if a page exists..........................................................................................................................688
Connect through a Proxy.....................................................................................................................690
Identify yourself using HTTP Authentification...................................................................................694
Talk to a CGI/Servlet...........................................................................................................................696
Write/Read cookies using HTTP.........................................................................................................697
Read a text file from the internet.........................................................................................................700
Read a GIF or CLASS from an URL save it locally............................................................................700
Resolve a relative URL........................................................................................................................702
File Size from URL..............................................................................................................................702
Using HTTPS protocol........................................................................................................................703
Fix certificate problem in HTTPS........................................................................................................704
Fetch a page from Google....................................................................................................................706
Upload a file.........................................................................................................................................707
Remove HTML tags from a file to extract only the TEXT.................................................................707
Extract links from an HTML page.......................................................................................................710
Call a web service (generated with BEA ServiceGen)........................................................................712
Do basic authentication when calling a webservice............................................................................714
Have a simple HTTP server.................................................................................................................715
Handle JSON Object............................................................................................................................717
HttpUrlConnection with GZIP encoding.............................................................................................727
Connect through a Proxy.....................................................................................................................730
Have timeout on socket connection.....................................................................................................733
Ping a server.........................................................................................................................................734
Get the Date from server......................................................................................................................735
Use Socket's setSoLinger()..................................................................................................................735
Use Socket's setTcpNoDelay()............................................................................................................736
Find who is connecting to a ServerSocket...........................................................................................736
Transfer a file via Socket.....................................................................................................................737
Check if a document exists in a Sharepoint library.............................................................................739
Delete a document in a Sharepoint library...........................................................................................741
Get a document from a Sharepoint library...........................................................................................743
Put or store a document in a Sharepoint library...................................................................................745
Handle MS Exchange public folders...................................................................................................747

xiii
Real's HowTo PDF version

Table of Contents
Open Source....................................................................................................................................................750
java-os..................................................................................................................................................750
Call Windows API...............................................................................................................................750
Call COM object..................................................................................................................................750
Create entity-relation diagram.............................................................................................................751
Java Remote desktop tool....................................................................................................................752
Create entity-relation diagram.............................................................................................................753
Launch a java program as a Windows EXE file..................................................................................753
Tools to handle CSV files....................................................................................................................755
Tools to handle Excel files...................................................................................................................756
Browse a Queue (JMS/MQ).................................................................................................................763
Convert a .class to .java file (decompiler)...........................................................................................763
Deploy an application as only 1 jar......................................................................................................765
Read an Outlook MSG file..................................................................................................................765
File/directory polling to detect change................................................................................................769
Jansi/Jcurses - Clear the console and control attributes.......................................................................770
Disable Checkstyle from code.............................................................................................................773
Create or process PDF files..................................................................................................................774
iText - Create a PDF............................................................................................................................776
Split a PDF file (using iText)...............................................................................................................777
Concatenate PDF files (using iText)....................................................................................................779
Convert TIF to PDF.............................................................................................................................780
Convert HTML to PDF using iText.....................................................................................................782
Convert HTML to PDF using YAHP..................................................................................................784
Convert PNG/JPG/GIF to PDF using iText.........................................................................................786
Print a PDF...........................................................................................................................................787
Extract text from a PDF using Apache Tika........................................................................................788
Detect and remove blank page in pdf (iText)......................................................................................789

Security............................................................................................................................................................792
java-security.........................................................................................................................................792
Encrypt a password..............................................................................................................................792
Create a checksum...............................................................................................................................797
Get the username..................................................................................................................................801
Get the username using NTLM from a JSP.........................................................................................802
Check if the current user belongs a specific Windows group/role......................................................804
Allow user:password in URL...............................................................................................................804
Input password from the console.........................................................................................................805
Prevent XSS exploit.............................................................................................................................806
Display a simple username/password Dialog from an Applet.............................................................808
Solve "Application blocked by security settings" message with unsigned Applet..............................811

xiv
Real's HowTo PDF version

Table of Contents
String/Number.................................................................................................................................................814
java-stringnumber................................................................................................................................814
*Read me*...........................................................................................................................................814
Convert from type X to type Y............................................................................................................814
Strip certain characters from String.....................................................................................................817
Replace/remove character in a String..................................................................................................818
Replace every occurences of a string within a string...........................................................................819
"Tokenize" a string..............................................................................................................................821
Split a string using String.split()..........................................................................................................827
Optimize String operations..................................................................................................................830
Remove spaces from a String..............................................................................................................832
Test if a String starts with a digit or uppercase letter..........................................................................833
Get InputStream from a String.............................................................................................................833
Easy String padding.............................................................................................................................834
Replace \r\n with the <br> tag.............................................................................................................836
Remove accent from letters (ex .é to e)...............................................................................................836
Apply a mask to a string......................................................................................................................840
Format a String (JDK1.5)....................................................................................................................841
Replace a "\" by "\\".............................................................................................................................842
Substitute tokens in a String................................................................................................................843
Compare accentuated letters................................................................................................................843
Create a String with a fixed length......................................................................................................845
Unquote a String..................................................................................................................................846
Escape HTML special characters from a String..................................................................................846
Unescape HTML special characters from a String..............................................................................849
Detect non-ASCII character in a String...............................................................................................853
Remove HTML tags from a file to extract only the TEXT.................................................................854
Extract links from an HTML page.......................................................................................................857
Convert a byte array to a Hex string....................................................................................................859
Apply proper uppercase and lowercase on a String.............................................................................861
Encode/Decode to/from Base64..........................................................................................................862
Justify string with wordwrap...............................................................................................................864
Shorten a long path..............................................................................................................................865
Ellipse a long string.............................................................................................................................869
Display an ASCII banner.....................................................................................................................870
Convert from type X to type Y............................................................................................................871
Type conversion (JDK1.5)...................................................................................................................874
Round a double....................................................................................................................................875
Display numbers with commas............................................................................................................876
Display numbers in scientific notation................................................................................................877
Display numbers with leading zeroes..................................................................................................879
Get a random number...........................................................................................................................880
Convert an UNSIGNED byte to a JAVA integer................................................................................880

xv
Real's HowTo PDF version

Table of Contents
String/Number
Deal with the big-endian and little-endian order.................................................................................882
Pass an integer by reference.................................................................................................................882
Pass floats as string literals to a method..............................................................................................882
Get random numbers............................................................................................................................883
Convert number to words.....................................................................................................................884
Arithmetic with double........................................................................................................................893
Detect even/odd number......................................................................................................................894
Convert bytes to megabytes.................................................................................................................894
Validate a number................................................................................................................................895
Get a unique identifier.........................................................................................................................896
Validate/Convert a number using the current Locale()........................................................................897
Transform a fraction to a Double.........................................................................................................899
Get short ordinal representation of a number......................................................................................900

Swing................................................................................................................................................................902
java-swing............................................................................................................................................902
*Read me*...........................................................................................................................................902
Change default component font...........................................................................................................902
Repaint problem under the mouse cursor (JDK1.2)............................................................................903
Set the LookAndFeel...........................................................................................................................903
Use any LookAndFeel on any plateform.............................................................................................903
Use a Timer..........................................................................................................................................904
Share ActionEvent handler..................................................................................................................905
Get default values for Swing-based user interface..............................................................................907
Have a systray icon (Windows)...........................................................................................................908
Close a JFrame under condition...........................................................................................................910
Maximize a JFrame..............................................................................................................................911
Capture System.out into a JFrame.......................................................................................................912
Remove the titlebar of JInternalFrame................................................................................................915
Have borders on a JWindow/JFrame...................................................................................................915
Display HTML in a JScrollPane..........................................................................................................915
Use a JOptionPane...............................................................................................................................916
Localize a JOptionPane dialog.............................................................................................................918
Customize a JOptionPane dialog.........................................................................................................920
Localize a JFileChooser.......................................................................................................................920
Select a directory with a JFileChooser.................................................................................................924
Disable the JFileChooser's 'New folder' button...................................................................................925
Validate a filename from a JFileChooser.............................................................................................927
Make a JFrame looks like a JDialog....................................................................................................928
Make a JFrame always visible.............................................................................................................929
Show a JFrame on a specific screen in a dual monitor configuration.................................................930
Make a frame not visible in the taskbar...............................................................................................930

xvi
Real's HowTo PDF version

Table of Contents
Swing
Based on JTextField content, enable or disable a JButton...................................................................931
Apply special filter to a JtextField.......................................................................................................932
Limit JTextField input to a maximum length......................................................................................936
Validate a value on the lostFocus event...............................................................................................937
Force the focus on a JTextfield when a JFrame is created..................................................................939
Stop the beep on JFormattedTextField................................................................................................940
Right justified JTextfield content........................................................................................................941
Set the focus on a particuliar JTextField..............................................................................................941
Make JTextField unselectable..............................................................................................................942
Disable copy paste functionality on JTextField...................................................................................942
Use a JTree to navigate in a site...........................................................................................................944
Expand or collapse a JTree..................................................................................................................951
Have a popup attached to a JTree........................................................................................................954
Traverse a JTree...................................................................................................................................956
Dotted Lines in a JTree........................................................................................................................958
Explore directories with a JTree..........................................................................................................958
Prevent JTree collapsing......................................................................................................................960
Single selection in a JTree...................................................................................................................960
Reduce JTree children indentation.......................................................................................................961
Use + or - for JTree Icons....................................................................................................................961
Change JTable header color.................................................................................................................963
Detect doubleclick on a JTable............................................................................................................964
Read a data file into a JTable...............................................................................................................966
Disable row selection in a JTable........................................................................................................969
Detect a data file modification and reload a JTable.............................................................................969
Hide a column in JTable......................................................................................................................971
Scroll a JTable to the last row..............................................................................................................973
Transfer a ResultSet to a JTable..........................................................................................................973
Have on a JScrollPane/JTable an horizontal JScrollbar......................................................................974
Make a JList select an item on doubleclick or the ENTER key..........................................................974
Make a JList like a scrolling text display.............................................................................................976
Have images in a JList.........................................................................................................................977
Add a row and clear a JList..................................................................................................................980
Sort a JList...........................................................................................................................................981
Double click on a JList........................................................................................................................982
Have a PopUp on a JList......................................................................................................................984
Make a JLabel selectable via the mouse..............................................................................................985
Change JLabel background color.........................................................................................................986
Bold/UnBold a JLabel.........................................................................................................................986
Multi-line JLabel..................................................................................................................................987
Underline in Swing..............................................................................................................................987
Update a JLabel....................................................................................................................................988

xvii
Real's HowTo PDF version

Table of Contents
Swing
Display a blinking JLabel....................................................................................................................988
Set the cursor position in a JTextArea.................................................................................................990
Have Multi-line string in a JToolTip...................................................................................................990
Change Tooltip color...........................................................................................................................991
Change a JTooltip font.........................................................................................................................991
Keep a JTooltip visible........................................................................................................................992
Display icon associated with an executable.........................................................................................993
Have items in JMenubar at rightmost position....................................................................................995
Have an JButton with an Image...........................................................................................................996
Trigger a click on a Button..................................................................................................................997

Thread..............................................................................................................................................................999
java-thread............................................................................................................................................999
Pipe the output of a thread to the input of another one........................................................................999
Pipe the output of a thread to the input of other threads....................................................................1001
Wait the for the completion of one thread.........................................................................................1004
Control a thread from outside............................................................................................................1005
Create a Timer object.........................................................................................................................1005
Pause the execution............................................................................................................................1007
Execute a method at regular interval.................................................................................................1007
Execute a process at regular interval.................................................................................................1009
Handle concurrent read/write.............................................................................................................1010
Communicate between threads using a Queue..................................................................................1012
Get a unique identifier.......................................................................................................................1017

Varia...............................................................................................................................................................1020
java-varia............................................................................................................................................1020
Use System time to generate unique ID.............................................................................................1020
Get a unique identifier.......................................................................................................................1020
Get the hard disk serial number or Motherboard Serial number.......................................................1022
Sort an array 1....................................................................................................................................1024
Sort an array 2....................................................................................................................................1026
Do a selection sort..............................................................................................................................1029
Validate a Social Security Number (canadian)..................................................................................1029
Validate a Credit Card Number.........................................................................................................1031
Obtain from where a Class is loaded.................................................................................................1035
Get the class name with or without the package................................................................................1036
See the generated bytecode................................................................................................................1037
Self-replicating programs...................................................................................................................1040
A curiosity..........................................................................................................................................1041
Common Bugs...................................................................................................................................1043
Number of the beast! :-).....................................................................................................................1044

xviii
Real's HowTo PDF version

Table of Contents
Varia
Use Java scripting engine (JDK 1.6)..................................................................................................1044
Pass or retrieve values from a scripting engine (JDK 1.6)................................................................1045
Preventing multiple instances of an application................................................................................1048
Trap JVM shutdown..........................................................................................................................1052
Minimize all programs on Windows to show the Desktop................................................................1052
Display a progress indicator in the console.......................................................................................1053

XML...............................................................................................................................................................1055
java-xml.............................................................................................................................................1055
Read me.............................................................................................................................................1055
Display XML using plain HTML......................................................................................................1056
Transform XML into HTML using XSLT.........................................................................................1057
Parse using SAX or DOM..................................................................................................................1059
Parse an XML string..........................................................................................................................1061
Create an XML document with DOM...............................................................................................1063
Attach a stylesheet to an XML file....................................................................................................1064
Create an XML file and attach an XSL.............................................................................................1065
Nicely display WEB.XML informations...........................................................................................1068
Serialize an object using XML..........................................................................................................1070
Convert flat file to XML using SAX.................................................................................................1071
Convert flat file to XML using DOM................................................................................................1073
Convert a ResultSet in XML.............................................................................................................1076
Parse with XPath................................................................................................................................1078
Strip extra spaces in a XML string....................................................................................................1082
Create an XML file and attach an XSL.............................................................................................1083
Use XML with Properties..................................................................................................................1087
Change a particular node in XML.....................................................................................................1088
Validate XML using a DTD..............................................................................................................1089
Validate XML using a XSD (XML schema).....................................................................................1093
Sanitize XML String..........................................................................................................................1099
Produce HTML entities when using XSLT.......................................................................................1100
Transform XML into CSV using XSLT............................................................................................1100
Create a RSS feed (part 1).................................................................................................................1102
Create a RSS feed (part 2).................................................................................................................1108
Parse a RSS XML file........................................................................................................................1115
Add a Live bookmark........................................................................................................................1117
Validate a RSS feed...........................................................................................................................1117
Attach a CSS to RSS feed..................................................................................................................1118
Handle JSON Object..........................................................................................................................1119

xix
Real's HowTo PDF version (november 2015).
This is the PDF version of the Real's HowTo Web site ( http://www.rgagnon.com/howto.html ). For
up-to-date content, please refer to the Web site. There are 4 files : Real's Java , Real's Javascript, Real's
Powerbuilder and Real's VBS and Misc Prog HowTo. Please don't make PDF versions available on the
internet (it's ok in intranet). From the PDF, you can't run the examples and the links to other How-to's are not
working.

If you feel that effort has been useful to you, perhaps you will consider giving something back? You can make
a donation through PayPal at https://www.paypal.com , make you donation to [email protected]
Contributions via PayPal are accepted in any amount using a credit card or checking account.

(Donations of any size gladly accepted)

This site is covered by the Creative Commons by-nc-sa license :


You can share, adapt and reuse but not for commercial reason. See the FAQ

Real's Howto copyright notice ( [email protected] )

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 CONTENT 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 PDF version (november 2015). 1


Real's HowTo PDF version

Real's HowTo PDF version (november 2015). 2


AWT
java-awt

Use the CardLayout manager


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0237.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 java.awt.Color;
import java.awt.Dimension;
import java.awt.LayoutManager;
import 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;

AWT 3
Real's HowTo PDF version

setBackground(co);
setLayout(la);
}

public Dimension getMinimumSize() {


return new Dimension(w,h);
}

public Dimension getPreferredSize() {


return new Dimension(w,h);
}
}

and then

import java.applet.Applet;
import java.awt.Button;
import java.awt.CardLayout;
import java.awt.Choice;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import 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");

Use the CardLayout manager 4


Real's HowTo PDF version

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

Use the CardLayout manager 5


Real's HowTo PDF version

if (c[i].isVisible()) {
t2.setText("" + (i+1));
break;
}
else
i ++;
}
}
}
}

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

Try it here.

Detect which card is visible with a CardLayout


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

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

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

[JDK1.1]

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

public class PopupTest extends Frame


implements ActionListener, MouseListener {

Detect which card is visible with a CardLayout 6


Real's HowTo PDF version

Hashtable popupTable = new Hashtable();

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

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

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

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

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

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

setVisible(true);
}

public void actionPerformed(ActionEvent e) {


/*

Use Popups 7
Real's HowTo PDF version

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

void setHash(Component c, PopupMenu p) {


/*
** associate a Component with a particular Popup
*/

Use Popups 8
Real's HowTo PDF version

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

Use a File Dialog


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

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

import java.awt.*;
public class UseFileDialog {

public String loadFile


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

public String saveFile


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

public static void main(String s[]) {


UseFileDialog ufd = new UseFileDialog();
System.out.println
("Loading : "
+ ufd.loadFile(new Frame(), "Open...", ".\\", "*.java"));

Use a File Dialog 9


Real's HowTo PDF version

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

Use TrueType font


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

[JDK1.4]
The names of the most common fonts supported by Java are TimesRoman, Courier, and Helvetica. To add
fonts, simply edit the properties.font file located in the lib of your JDK installation.

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

Kaufmann.0=Kaufmann BT, ANSI_CHARSET

To use it, in a java program :

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

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

Use TrueType font 10


Real's HowTo PDF version

[JDK1.5]
@todo

Display available fonts


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

[JDK1.1]

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

[JDK1.2]

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

Font with 3D effect


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0312.html

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

public class SimpleApplet extends Applet {

Display available fonts 11


Real's HowTo PDF version

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

Use the System Clipboard


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

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

public class Java2Clipboard implements ClipboardOwner {


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

public void toClipboard() {


SecurityManager sm = System.getSecurityManager();

Font with 3D effect 12


Real's HowTo PDF version

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

public void lostOwnership(Clipboard clip, Transferable tr) {


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

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

Maximize a Frame
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0222.html

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


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

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

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

Latest JDK provides more ways to do that.

JDK1.4

import java.awt.*;
...
GraphicsDevice device;
Frame frame = new Frame();
device =
GraphicsEnvironment.
getLocalGraphicsEnvironment().
getDefaultScreenDevice();
if ( device.isFullScreenSupported() ) {
device.setFullScreenWindow(frame);
}
else {

Use the System Clipboard 13


Real's HowTo PDF version

System.err.println("Full screen not supported");


}

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

import java.awt.*;

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

Maximize a Frame 14
Real's HowTo PDF version

Center a Frame/Dialog
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0223.html

// centers the dialog within the screen [1.1]


// (put that in the Frame/Dialog class)
public void centerScreen() {
Dimension dim = getToolkit().getScreenSize();
Rectangle abounds = getBounds();
setLocation((dim.width - abounds.width) / 2,
(dim.height - abounds.height) / 2);
super.setVsible(true);
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);

Center a Frame/Dialog 15
Real's HowTo PDF version

Close a Frame
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0225.html

[JDK1.0.2]

public boolean handleEvent(Event evt) {


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

[JDK1.1 Method 1]

public aFrame extends Frame implements WindowListener {


public aFrame(){
addWindowListener( this );
}
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

Close a Frame 16
Real's HowTo PDF version

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

Call events on a Frame from a Panel


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

Call events on a Frame from a Panel 17


Real's HowTo PDF version

}
}

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

[TestEventFrame.java]

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

public class TestEventFrame extends Frame implements


ActionListener, WindowListener {
TestEventPanel p1;
Button b1;

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

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


add(b1);

// the Panel with 2 buttons on it


add(p1);
createFrame();

// add the actionlistener


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

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

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

Call events on a Frame from a Panel 18


Real's HowTo PDF version

System.out.println("dummy receive :" + ae.getActionCommand());


}

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

public void windowClosing(WindowEvent e) {


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

and finally

[Java0268.java]

import java.awt.*;

public class Java0268 extends java.applet.Applet {


TestEventFrame myTestEventFrame;

public void init() {


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

Try it here.

Set the small top-left icon on a Frame


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

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

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.

Set the small top-left icon on a Frame 19


Real's HowTo PDF version

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

Prevent a Frame to be resized


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

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

public class TestNoMaximize {


MyFrame theFrame;

public static void main (String args[]){


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

class MyFrame extends Frame {


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

Prevent a Frame to be resized 20


Real's HowTo PDF version

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

public void paint(Graphics g) {


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

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

Embed an image into a Frame


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

Embed an image into a Frame 21


Real's HowTo PDF version

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

public void update( Graphics g) {


paint(g);
}

public void paint(Graphics g) {


if(image != null) {

Embed an image into a Frame 22


Real's HowTo PDF version

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 :

Display a message box


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0242.html

Display a message box 23


Real's HowTo PDF version

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

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

Display a message box 24


Real's HowTo PDF version

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

Display a Splash screen


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

This Splash class display a window containing a specified image while a parent Frame is doing its
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);

Display a Splash screen 25


Real's HowTo PDF version

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 (jht.gif) as the splash image.

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

public class TestSplash {


MyFrame theFrame;

Display a Splash screen 26


Real's HowTo PDF version

public static void main (String args[]){


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

private void createMainFrame() {


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

class MyFrame extends Frame {


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

// dummy delay so we can see the Splash!


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

Vibrate a Window
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0622.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;

Vibrate a Window 27
Real's HowTo PDF version

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);
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 Swing-oriented, 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);

Vibrate a Window 28
Real's HowTo PDF version

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

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

Vibrate a Window 29
Real's HowTo PDF version

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.

Limit TextField input to numeric value


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

[JDK1.0.2]

// You still have to trap the InvalidNumberFormat


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

public void init() {


setLayout(new FlowLayout());
textField1 = new TextField(10);
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]

Limit TextField input to numeric value 30


Real's HowTo PDF version

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

Limit TextField input to a maximum length


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0227.html

[JDK11]

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

public class TextFieldWithLimit extends TextField


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

Limit TextField input to a maximum length 31


Real's HowTo PDF version

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

React to the ENTER key in a Textfield


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

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

public class testENTER extends Applet


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

React to the ENTER key in a Textfield 32


Real's HowTo PDF version

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

Make the ENTER key act like the TAB key


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0254.html

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

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

public class MyTextField extends TextField {


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

Make the ENTER key act like the TAB key 33


Real's HowTo PDF version

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

Reset all textfields in one shot


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

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

public class FirstApplet extends Applet implements


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

public void init() {


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

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b)

Reset all textfields in one shot 34


Real's HowTo PDF version

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>

Limit a TextField to Uppercase


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

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

public class UpperTF extends Frame {


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

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

addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {

Limit a TextField to Uppercase 35


Real's HowTo PDF version

System.exit(0);
}
}
);
}

public Dimension getPreferredSize() {


return new Dimension(200,200);
}
}

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

This implementation of an ImageButton requires JDK1.1 and is a good example of the new Event

architecture. This ImageButton needs 2 GIF images representing the normal and pressed state ( ).
Also a method to disable the button by using a special filter is given.

[ImageButton.java]

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

public class ImageButton extends Canvas {


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

public ImageButton(URL up_b, URL down_b) {


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

public void InitImage(URL up, URL down) {


MediaTracker tracker;

Have an ImageButton 36
Real's HowTo PDF version

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)) {
clicked=true;

Have an ImageButton 37
Real's HowTo PDF version

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;

Have an ImageButton 38
Real's HowTo PDF version

}
}
}

[TestImageButton.java]

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

public class TestImageButton extends Applet


implements ActionListener,ItemListener {
ImageButton ib;
Checkbox c;

public void init() {


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

public void actionPerformed(ActionEvent e) {


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

public void itemStateChanged(ItemEvent ie) {


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

Reset a checkbox group


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

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

Reset a checkbox group 39


Real's HowTo PDF version

public class radio extends Applet {


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

public boolean action(Event e, Object o) {


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

Set the listbox width


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

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

class myListbox extends List {


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

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


super(r,m);
width = n;
height = r;
setFont(f);
}

public Dimension preferredSize (){


FontMetrics fm=getFontMetrics(getFont());

Set the listbox width 40


Real's HowTo PDF version

// the character W used as reference


return new Dimension
(fm.charWidth('W')*width, fm.getHeight()*height);
}
}

Align the column in a List


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

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

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

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

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

public void insertItem(List lbx,


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

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

Have a srolling text display using a List


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

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

Align the column in a List 41


Real's HowTo PDF version

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

Label dynamic resizing


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

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

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


aLabel.resize (aLabel.preferredSize());

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

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


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

Have a srolling text display using a List 42


Real's HowTo PDF version

this.validate();

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

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


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

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

Label dynamic resizing 43


Real's HowTo PDF version

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

Make a TextArea "word-wrap"


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0241.html

Simply create the TextArea with no horizontal scrollbar.

myTextArea = new TextArea


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

Synchronize a TextArea versus a Choice


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

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

class ChoiceEx extends Frame implements ItemListener {


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

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


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

Make a TextArea "word-wrap" 44


Real's HowTo PDF version

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

Display underlined text


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

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

public class underlineText extends Applet{


String s = "Underlined text";
int x=10;
int y=10;

public void init() {}

public void paint(Graphics g) {


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

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


Check this How-to for underlined text in Swing.

Display vertical text


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

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

public class verticalText extends Applet {

Synchronize a TextArea versus a Choice 45


Real's HowTo PDF version

String s = "Vertical text";


int x=10;
int y=10;
int v;
public void init() {}

public void paint(Graphics g) {


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

[JDK1.4]

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

public void paint(Graphics g){


Graphics2D g2d = (Graphics2D)g;

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

Have Label with many lines


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

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

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

Display vertical text 46


Real's HowTo PDF version

public class MultiLineLabel extends Canvas {


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

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


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

public MultiLineLabel(String string, int i) {


this(string, i, false);
}

public MultiLineLabel(String string) {


this(string, 0);
}

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

public void addNotify() {


super.addNotify();
calc();
}

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


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

Have Label with many lines 47


Real's HowTo PDF version

public int getLeftRightMargin() {


return leftRightMargin;
}

public void setLeftRightMargin(int i) {


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

public int getAlignment() {


return alignment;
}

public void setAlignment(int i) {


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

public int getTopBottomMargin() {


return topBottomMargin;
}

public void setTopBottomMargin(int i) {


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

public void setFont(Font font) {


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

public Dimension getMinimumSize() {


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

public Dimension getPreferredSize() {


return getMinimumSize();
}

Have Label with many lines 48


Real's HowTo PDF version

public boolean getBorder() {


return border;
}

public void setBorder(boolean flag) {


border = flag;
}

public void setText(String s) {


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

public String getText() {


return text;
}

public Color getBorderColor() {


return borderColor;
}

public void setBorderColor(Color c) {


borderColor = c;
}

private void calc() {


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

public void update(Graphics g) {

Have Label with many lines 49


Real's HowTo PDF version

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

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

Have Label with many lines 50


Real's HowTo PDF version

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

Have a Label with underlined text


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

[UnderlinedLabel.java]

import java.awt.*;

public class UnderlinedLabel extends Label {


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

public UnderlinedLabel(String text){


super(text);
}

public void paint(Graphics g) {


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

[TestUnderlinedLabel.java]

Have a Label with underlined text 51


Real's HowTo PDF version

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

public class TestUnderlinedLabel extends Applet {


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

[testapplet.html]

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

Check this How-to for underlined text in Swing.

Have a Label acting as HTML HREF (URLLabel)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0273.html

[URLLabel.java]

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

public class URLLabel extends Label {


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

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


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

public URLLabel
(Applet applet , String url, String text, String target){
super(text);
setForeground(unvisitedURL);
try {

Have a Label acting as HTML HREF (URLLabel) 52


Real's HowTo PDF version

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 How-to");
add(ull1);
URLLabel ull2 = new URLLabel(this,
"http://www.rgagnon.com/bigindex.html",
"Java How-to BigIndex");
add(ull2);
URLLabel ull3 = new URLLabel(this,
"http://www.rgagnon.com/javadetails/java-0001.html",
"Java How-to 0001");

Have a Label acting as HTML HREF (URLLabel) 53


Real's HowTo PDF version

add(ull3);
URLLabel ull4 = new URLLabel(this,
"http://www.rgagnon.com/javadetails/java-0002.html",
"Java How-to 0002");
add(ull4);
validate();
}
}

[testapplet.html]

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

Try it here.

Display a GIF in a Canvas


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

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

public class ImageCanvas extends Canvas {


Image image;

public ImageCanvas(String name) {


MediaTracker media = new MediaTracker(this);
image = Toolkit.getDefaultToolkit().getImage(name);
media.addImage(image, 0);
try {
media.waitForID(0);
}
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[]) {

Display a GIF in a Canvas 54


Real's HowTo PDF version

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

Embed an image into a Frame


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

A given image is tiled as the frame background.

The result is not too good with Label...

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

public class ImageFrame extends Frame {

private Image image;

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

setLayout(new FlowLayout());

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

Embed an image into a Frame 55


Real's HowTo PDF version

setSize(500, 500);

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

public void update( Graphics g) {


paint(g);
}

public void paint(Graphics g) {


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

static public void main(String[] args) {


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

The result :

Embed an image into a Frame 56


Real's HowTo PDF version

Load several images from a single GIF


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0239.html

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

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

public class strip extends Applet{


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

public void init(){


loadImages("item.gif");
}

Load several images from a single GIF 57


Real's HowTo PDF version

public void paint(Graphics g) {


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

public void loadImages(String s) {


MediaTracker t=new MediaTracker(this);
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;
}
}
}

Load an Image from a JAR file


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

[JDK1.1 application]

String imgName = "image.jpg";


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

Load an Image from a JAR file 58


Real's HowTo PDF version

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]

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


button.setIcon(new ImageIcon(url));

Load an Image from a JAR file (again)


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

public static ImageIcon getImageIcon(String name) {


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

Load an Image from a JAR file (again) 59


Real's HowTo PDF version

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

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

public static Icon getIconForType(int iconType) {


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

A list of what icons are available can be found here

Scale an Image
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0243.html

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

public class app extends java.applet.Applet {


Image source;
Image resizedImage;

public void init() {


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

Scale an Image 60
Real's HowTo PDF version

resizedImage = createImage(prod);
media.addImage(resizedImage,1);
media.waitForID(1);
}
catch(InterruptedException e) {}
}

public void paint(Graphics g) {


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

Try it here.

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

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

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

public class ScaleJPG {


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

public static void main(String[] args) {


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

Scale an Image 61
Real's HowTo PDF version

}
}
}

Example :

>java ScaleJPG javahowto.jpg 250 70 javahowto2.jpg

Input:

Ouput:

Fade an image
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0249.html

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

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

public class FadeImage extends Applet {


Image img, faded;
int level, sign;
MediaTracker tracker;
AlphaFilter f;
FilteredImageSource fis;

public void init() {


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

Fade an image 62
Real's HowTo PDF version

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 {

Fade an image 63
Real's HowTo PDF version

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

class AlphaFilter extends RGBImageFilter {


private int level;

public AlphaFilter() {
canFilterIndexColorModel = true;
}

public void setLevel(int lev) {


level = lev;
}

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


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

Try it here.

Rotate an image
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0248.html

The following snippet rotates an image (90 degrees). The applet assumes the dimension 32x32 for the image.

You may want to grap this image for testing purpose.

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

public class RotateGumby extends Applet {


Image img = null;
Image rot = null;

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


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

Rotate an image 64
Real's HowTo PDF version

public void init() {


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

public void update( Graphics g) {


paint(g);
}

public void paint(Graphics g) {


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

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

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

public class RotatePanel extends JPanel {


private Image image;
private double currentAngle;

public RotatePanel(Image image) {


this.image = image;
MediaTracker mt = new MediaTracker(this);
mt.addImage(image, 0);
try {
mt.waitForID(0);

Rotate an image 65
Real's HowTo PDF version

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

Rotate an image 66
Real's HowTo PDF version

Create a scrollable canvas


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

JDK1.1 using a ScrollPane

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

public class apptest extends Applet {


Canvas c;
ScrollPane s;

public void init() {


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

class myCanvas extends Canvas {


Image buffImage;
Graphics offscreen;
boolean initDone = false;

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

public void update(Graphics g) {


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

public void initpaint(Graphics g) {


try {
buffImage = this.createImage(500, 500);
offscreen = buffImage.getGraphics();
offscreen.setColor(Color.black);
offscreen.fillRect(0, 0, 500, 500);
offscreen.setColor(Color.white);
offscreen.setFont(new Font("Courier", Font.ITALIC, 42));

Create a scrollable canvas 67


Real's HowTo PDF version

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

Create a scrollable canvas 68


Real's HowTo PDF version

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

Create a scrollable canvas 69


Real's HowTo PDF version

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

Use an Image as the Applet background


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

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

// TILE BACKGROUND
// in the HTML use :

Use an Image as the Applet background 70


Real's HowTo PDF version

// 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>
&LT;/HMTL&GT;

Try it here.

Use an Image as the Applet background 71


Real's HowTo PDF version

Have a simple Image browser


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

[imagelist.txt]

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

[application version]

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

public class ImageBrowser {


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

class AFrame extends Frame implements ActionListener {


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

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

public void actionPerformed (ActionEvent ae) {

Have a simple Image browser 72


Real's HowTo PDF version

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

Have a simple Image browser 73


Real's HowTo PDF version

import java.net.*;
import java.io.*;

public class ImageBrowserApplet extends Applet {


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

class APanel extends Panel implements ActionListener {


private List lbx;
private MyCanvas can;
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 =

Have a simple Image browser 74


Real's HowTo PDF version

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 try this example here

Simulate a "mouse over" event to toggle an image


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0264.html

Use a special Canvas to preload 2 GIFs, and using a MouseListener simply toggle the image.

[JDK1.1]

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

public class ToggleGifCanvas extends Canvas


implements MouseListener {
Image img1, img2;
int index = 0;
MediaTracker tracker;

public ToggleGifCanvas(URL n1, URL n2) {


tracker = new MediaTracker(this);
try {

Simulate a "mouse over" event to toggle an image 75


Real's HowTo PDF version

img1 = Toolkit.getDefaultToolkit().getImage(n1);
img2 = Toolkit.getDefaultToolkit().getImage(n2);
tracker.addImage(img1,0);
tracker.addImage(img2,1);
tracker.waitForAll();
addMouseListener(this);
}
catch (Exception e) {
e.printStackTrace();
}
}

public void paint(Graphics g) {


if (img1 != null) {
if (index == 0) {
g.drawImage(img1,0,0,this);
index++;
}
else {
g.drawImage(img2,0,0,this);
index--;
}
}
}

public Dimension getPreferredSize (){


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

public void mouseClicked(MouseEvent e) {}


public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {
index = 1;
repaint();
}
public void mouseExited(MouseEvent e) {
index = 0;
repaint();
}
}

To use such Canvas, try something like this. This example needs our Gumby GIFs ( and ).

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

public class TestToogleGifCanvas extends Applet {


ToggleGifCanvas tgc;

public void init() {

Simulate a "mouse over" event to toggle an image 76


Real's HowTo PDF version

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.

Hide the mouse cursor


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0440.html

One way is to use a transparent GIF as the cursor or create one.

int[] pixels = new int[16 * 16];


Image image = Toolkit.getDefaultToolkit().createImage(
new MemoryImageSource(16, 16, pixels, 0, 16));
Cursor transparentCursor =
Toolkit.getDefaultToolkit().createCustomCursor
(image, new Point(0, 0), "invisibleCursor");

Make a color transparent


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0265.html

Here we have an Image with a blue background like and we want to display it in an Applet with a white
background. All we have to do is to look for the blue color with the "Alpha bits" set to opaque and make them
transparent.

[Transparency.java]

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

public class Transparency {


public static Image makeColorTransparent
(Image im, final Color color) {
ImageFilter filter = new RGBImageFilter() {

Hide the mouse cursor 77


Real's HowTo PDF version

// the color we are looking for... Alpha bits are set to opaque
public int markerRGB = color.getRGB() | 0xFF000000;

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


if ( ( rgb | 0xFF000000 ) == markerRGB ) {
// Mark the alpha bits as zero - transparent
return 0x00FFFFFF & rgb;
}
else {
// nothing to do
return rgb;
}
}
};

ImageProducer ip = new FilteredImageSource(im.getSource(), filter);


return Toolkit.getDefaultToolkit().createImage(ip);
}
}

[app.java]

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

public class app extends java.applet.Applet {


Image GifOriginalWithWithBlueBackground;
Image GifModifiedWithTransparentBackground;

public void init() {


setBackground(new Color(0).white);

MediaTracker media = new MediaTracker(this);


// image of our friend, Gumby with a blue background
GifOriginalWithWithBlueBackground =
getImage(getDocumentBase(),"gumbyblu.gif");
media.addImage(GifOriginalWithWithBlueBackground,0);
try {
media.waitForID(0);
GifModifiedWithTransparentBackground =
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);
}
}

Make a color transparent 78


Real's HowTo PDF version

[x.html]

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

Save an Image as a GIF or JPEG file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0266.html

Take a look at the following package :

http://www.obrador.com/essentialjpeg/jpeg.htm for JPEG


http://www.acme.com for GIF
http://rsb.info.nih.gov/ij/ can display BMP and save as GIF or TIFF

With JDK1.2, Sun introduces a new package called JIMI (available for download at their Web site. With this
package, it's easy to convert a Java Image to a JPEG image file.

double w = 200.0;
double h = 200.0;
BufferedImage image = new BufferedImage(
(int)w,(int)h,BufferedImage.TYPE_INT_RGB);

Graphics2D g = (Graphics2D)image.getGraphics();
g.drawLine(0,0,w,h);

try {
File f = new File("myimage.jpg");
JimiRasterImage jrf = Jimi.createRasterImage(image.getSource());
Jimi.putImage("image/jpeg",jrf,new FileOutputStream(f));
}
catch (JimiException je) {
je.printStackTrace();}

Another way is to use the undocumented com.sun.image.codec.jpeg package.

// [JDK1.2]
// img is a Java Image
//
BufferedImage bimg = null;
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);

Save an Image as a GIF or JPEG file 79


Real's HowTo PDF version

try {
pg.grabPixels();
}
catch(InterruptedException ie) {
ie.printStackTrace();
}

bimg = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);


bimg.setRGB(0,0,w,h,pixels,0,w);

// Encode as a JPEG
FileOutputStream fos = new FileOutputStream("out.jpg");
JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(fos);
jpeg.encode(bimg);
fos.close();

Since JDK1.4.2, javax.imageio.ImageIO lets you save and restore Images to disk in a platform independent
format. "png" and "jpeg" format are supported. With ImageIO, instead of Image you use BufferedImage
which is a subclass of Image.

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

public class FileOperations {

public static BufferedImage readImageFromFile(File file)


throws IOException
{
return ImageIO.read(file);
}

public static void writeImageToJPG


(File file,BufferedImage bufferedImage)
throws IOException
{
ImageIO.write(bufferedImage,"jpg",file);
}
}

Use the same background color as the browser


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0234.html

// in the HTML, use


// PARAM NAME="bgColor" VALUE="B8B5AE"
// (where VALUE is the same hexadecimal value
// as the HTML COLOR value)

Use the same background color as the browser 80


Real's HowTo PDF version

// in the APPLET tag


// in the JAVA init method :
Color bgcolor = new Color(
Integer.valueOf(getParameter("BGCOLOR"), 16).intValue());
setBackground(bgcolor);

Do simple animation using Images


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0262.html

By using a Thread, we switch between 2 GIFs ( and )

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

public class AnimationGifApplet extends Applet {


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

public void init() {


img = new Image[2]; // 2 images in animation
maxImg = img.length - 1;
tracker = new MediaTracker(this);
try {
// images loading
img[0] = getImage(new URL(getDocumentBase(), "images/gumby.gif"));
img[1] = getImage(new URL(getDocumentBase(), "images/gumby2.gif"));
tracker.addImage(img[0],0);
tracker.addImage(img[1],1);
tracker.waitForAll();
}
catch (Exception e) {
e.printStackTrace();
}

AnimationThread at = new AnimationThread();


at.delayedAnimation(this, 500);
at.start();
}

public void paint(Graphics g) {


if (img[0] != null) {
g.drawImage(img[index],0,0,this);
index = (index <maxImg) ? index + 1 : 0;
}

Do simple animation using Images 81


Real's HowTo PDF version

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.

Do simple animation to show "work in progress"


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0263.html

Like the previous How-to, using a Thread, we switch between 2 GIFs, for example ( and ).

Click the button to simulate some work, click again to terminate the "work in progress"

[JDK1.1]

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

public class AnimationProgress extends Applet

Do simple animation to show "work in progress" 82


Real's HowTo PDF version

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

Do simple animation to show "work in progress" 83


Real's HowTo PDF version

this.animationApplet = a;
this.delay = delay;
}

public void run() {


while (true) {
try {
sleep(delay);
animationApplet.animate();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
}

Get the color of a specific pixel


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0257.html

We assume that we have an Image called picture

pixels = new int[width*height];


PixelGrabber pg =
new PixelGrabber(picture, 0, 0, width, height, pixels, 0, width);
try {
pg.grabPixels();
}
catch (InterruptedException e) { }

From here, individual pixel can be accessed via the pixels array.

int c = pixels[index]; // or pixels[x * width + y]


int red = (c & 0x00ff0000) >> 16;
int green = (c & 0x0000ff00) >> 8;
int blue = c & 0x000000ff;
// and the Java Color is ...
Color 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);

Get the color of a specific pixel 84


Real's HowTo PDF version

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

Do "rubber-band" drawing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0251.html

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

public class SimpleCAD extends Applet {


int w = 200;
int h = 200;
Vector lines = new Vector();
int np = 0;
int x1,y1;
int x2,y2;
int xl,yl;
Image offImg;
Graphics offGra;
Button btnClear, btnUndo;

public void init() {


setLayout(new FlowLayout());
btnClear = new Button("Clear");
btnUndo = new Button("Undo");
add(btnClear);
add(btnUndo);
setBackground(new Color(0).black);
setForeground(new Color(0).white);
}

public void Dragupdate(Graphics g) {


/*
** rubber-band effect
*/
g.setXORMode(getBackground());
setForeground(new Color(0).blue);
if (xl != -1){
// erase the old line
g.drawLine(x1, y1, xl, yl);
if (x2 != -1) {
// draw the new one
g.drawLine(x1, y1, x2, y2);

Do "rubber-band" drawing 85
Real's HowTo PDF version

}
}
}

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

Do "rubber-band" drawing 86
Real's HowTo PDF version

public boolean action(Event e, Object o) {


if (e.target == btnClear) resetDrawing();
if (e.target == btnUndo) undo();
return true;
}

public void undo() {


if (np>0) {
lines.removeElementAt(np-1);
np--;
repaint();
}
}

public void resetDrawing() {


lines.removeAllElements();
np=0;
repaint();
}
}

Convert RGB value to Hex (to be used in HTML)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0255.html

import java.awt.*;
public class Color2Hex {
public static void main( String[] args ) {
if (args.length != 3) {
System.out.println("Color2Hex r g b");
}
else {
int i = Integer.parseInt(args[0]);
int j = Integer.parseInt(args[1]);
int k = Integer.parseInt(args[2]);

Color c = new Color(i,j,k);


System.out.println
( "hex: " + Integer.toHexString( c.getRGB() & 0x00ffffff ) );
}
}
}

Draw a line or set a pixel in my own image


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0250.html

Convert RGB value to Hex (to be used in HTML) 87


Real's HowTo PDF version

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

Draw dashed line


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0224.html

public void drawDashedLine(Graphics g,int x1,int y1,int x2,int y2,


double dashlength, double spacelength) {
if((x1==x2)&&(y1==y2)) {
g.drawLine(x1,y1,x2,y2);
return;
}
double linelength=Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
double yincrement=(y2-y1)/(linelength/(dashlength+spacelength));
double xincdashspace=(x2-x1)/(linelength/(dashlength+spacelength));
double yincdashspace=(y2-y1)/(linelength/(dashlength+spacelength));

Draw a line or set a pixel in my own image 88


Real's HowTo PDF version

double xincdash=(x2-x1)/(linelength/(dashlength));
double yincdash=(y2-y1)/(linelength/(dashlength));
int counter=0;
for (double i=0;i<linelength-dashlength;i+=dashlength+spacelength){
g.drawLine((int) (x1+xincdashspace*counter),
(int) (y1+yincdashspace*counter),
(int) (x1+xincdashspace*counter+xincdash),
(int) (y1+yincdashspace*counter+yincdash));
counter++;
}
if ((dashlength+spacelength)*counter<=linelength)
g.drawLine((int) (x1+xincdashspace*counter),
(int) (y1+yincdashspace*counter),
x2,y2);
}

Draw a line with a thickness


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0260.html

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

public class thickLine extends Applet {

public void init( ) { }

public void paint( Graphics g ) {


drawThickLine
(g, 0, 0, getSize().width, getSize().height, 5, new Color(0).black);
drawThickLine
(g, 0, getSize().height, getSize().width, 0, 5, new Color(0).red);

drawThickLine
(g, getSize().width/2, 0, getSize().width/2, getSize().height, 8,
new Color(0).green);
drawThickLine
(g, 0, getSize().height/2, getSize().width, getSize().height/2, 12,
new Color(0).blue);
}

public void drawThickLine(


Graphics g, int x1, int y1, int x2, int y2, int thickness, Color c) {
// The thick line is in fact a filled polygon
g.setColor(c);
int dX = x2 - x1;
int dY = y2 - y1;
// line length
double lineLength = Math.sqrt(dX * dX + dY * dY);

Draw dashed line 89


Real's HowTo PDF version

double scale = (double)(thickness) / (2 * lineLength);

// The x,y increments from an endpoint needed to create a rectangle...


double ddx = -scale * (double)dY;
double ddy = scale * (double)dX;
ddx += (ddx > 0) ? 0.5 : -0.5;
ddy += (ddy > 0) ? 0.5 : -0.5;
int dx = (int)ddx;
int dy = (int)ddy;

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


int xPoints[] = new int[4];
int yPoints[] = new int[4];

xPoints[0] = x1 + dx; yPoints[0] = y1 + dy;


xPoints[1] = x1 - dx; yPoints[1] = y1 - dy;
xPoints[2] = x2 - dx; yPoints[2] = y2 - dy;
xPoints[3] = x2 + dx; yPoints[3] = y2 + dy;

g.fillPolygon(xPoints, yPoints, 4);


}
}

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

Draw a line with a thickness 90


Real's HowTo PDF version

public static void main( String [] args ){


TestLine tl = new TestLine();
tl.setVisible( true );
}
}

class MyPanel extends JPanel {


final static BasicStroke stroke = new BasicStroke(2.0f);
final static BasicStroke wideStroke = new BasicStroke(8.0f);

public MyPanel(){}

public void paintComponent( Graphics g ){


Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint
(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke( stroke );
g2.draw(new Line2D.Double(10.0, 10.0, 100.0, 10.0));
g2.setStroke( wideStroke );
g2.draw(new Line2D.Double(10.0, 50.0, 100.0, 50.0));
}
}

Draw a pie chart


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0261.html

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

public class Graph extends Applet {


int depth, radius;

public void init() {


float value;
String at = getParameter("width");
radius = (at != null) ? Integer.valueOf(at).intValue() : 100;
at = getParameter("depth");
depth = (at != null) ? Integer.valueOf(at).intValue() : 20;
at = getParameter("values");
PieChartCanvas c = new PieChartCanvas(radius, depth);
setLayout(new BorderLayout());

// Create Hashtable to map color name (String) to Color type


Hashtable colors = new Hashtable();

Draw a pie chart 91


Real's HowTo PDF version

colors.put("green", Color.green);
colors.put("red", Color.red);
colors.put("blue", Color.blue);
colors.put("yellow", Color.yellow);
colors.put("magenta", Color.magenta);
colors.put("cyan", Color.cyan);
colors.put("orange", Color.orange);
colors.put("pink", Color.pink);
colors.put("white", Color.white);
colors.put("black", Color.black);

// "value-color,value-color,..."
StringTokenizer t = new StringTokenizer(at, ",");
String s;
int i;
while (t.hasMoreTokens()) {
s = t.nextToken();
i = s.indexOf('-');
value = Float.valueOf(s.substring(0, i)).floatValue();
c.addSlice(value, (Color)colors.get(s.substring(i + 1)));
}

resize(c.getMinimumSize().width, c.getMinimumSize().height);
add("Center", c);
}
}

class PieChartCanvas extends Canvas {


/*
** author Ciaran Treanor [email protected]
*/
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());

Draw a pie chart 92


Real's HowTo PDF version

offGraphics.fillRect(0, 0, d.width, d.height);


}

// do the 3d effect
for(int x = depth; x >= 1; x--) {
startAngle = -45;
for(int i = 0; i < numSlices; i++) {
offGraphics.setColor(color[i].darker());
angle = Math.round(360 * (value[i] / total));
offGraphics.fillArc(0, x, radius, (int)(radius / aspectFudge),
startAngle, (int)angle);
startAngle += angle;
}
}

// draw the pie slice


startAngle = -45;
for(int i = 0; i < numSlices; i++) {
offGraphics.setColor(color[i]);
angle = Math.round(360 * (value[i] / total));
offGraphics.fillArc(0, 0, radius, (int)(radius / aspectFudge),
startAngle, (int)angle);
startAngle += angle;
}
g.drawImage(gfxBuff, 0, 0, null);
}

public void addSlice(float value, Color color) {


this.value[numSlices] = value;
this.color[numSlices++] = color;
total += value;
}

public Dimension getPreferredSize() {


return getMinimumSize();
}

public Dimension getMinimumSize() {


return new Dimension(radius, (int)((radius / aspectFudge) + depth));
}
}

[JavaPie.hmtl]

<HTML>
<TABLE><TR><TD>
<APPLET CODE=Graph.class WIDTH=150 HEIGHT=150>
<PARAM NAME="depth" VALUE="30">
<PARAM NAME="width" VALUE="120">
<PARAM NAME="values" VALUE="1-red,5-green,7-blue">
</APPLET>
<TD>
<TABLE>
<TR><TD>item 1<TD BGCOLOR="#FF0000">

Draw a pie chart 93


Real's HowTo PDF version

<TR><TD>item 2<TD BGCOLOR="#008000">


<TR><TD>item 3<TD BGCOLOR="#0000FF">
</TABLE>
</TABLE>
</HMTL>

Try it here

Draw faster rectangles


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0364.html

Thanks to Chikirev Sergey

It seems that drawRoundRect(.) is 1,5 faster then drawRect(..) , because one of them is completely native.

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

public class Class1 extends Frame implements ActionListener{


public void paint(Graphics g){
super.paint(g);
long t=System.currentTimeMillis();
for(int i=0;i<10000;i++){
g.drawRect(10,70,100,50);
}
t=System.currentTimeMillis()-t;
g.drawString(String.valueOf(t),10,70);
t=System.currentTimeMillis();
for(int i=0;i<10000;i++){
g.drawRoundRect(10,130,100,50,0,0);
}
t=System.currentTimeMillis()-t;
g.drawString(String.valueOf(t),10,130);
}

public void actionPerformed(ActionEvent p1){


repaint(0,10,200,300);
}

public static void main (String[] args){


Class1 c=new Class1();
c.setSize(300,300);
c.setLayout(new BorderLayout());
Button b=new Button("Refresh");
c.add(BorderLayout.SOUTH , b);
b.addActionListener(c);
c.show();
}
}

Draw faster rectangles 94


Real's HowTo PDF version

Get a screen capture and save it as a JPEG


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0489.html

The screen capture is done with java.awt.Robot.

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;

class ScreenCapture {
public static void main(String args[]) throws
AWTException, IOException {
// capture the whole screen
BufferedImage screencapture = new Robot().createScreenCapture(
new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) );

// Save as JPEG
File file = new File("screencapture.jpg");
ImageIO.write(screencapture, "jpg", file);

// Save as PNG
// File file = new File("screencapture.png");
// ImageIO.write(screencapture, "png", file);
}
}

To capture a specific area

BufferedImage screencapture = new Robot().createScreenCapture(


new Rectangle( 15, 15, 150, 150));

To capture a specific visual object

BufferedImage image = new Robot().createScreenCapture(


new Rectangle( myframe.getX(), myframe.getY(),
myframe.getWidth(), myframe.getHeight() ) );

Detect a double click versus a simple click


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0235.html

Get a screen capture and save it as a JPEG 95


Real's HowTo PDF version

[JDK1.02]

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

public class d extends Applet {

int dClkRes = 300; // double-click speed in ms


long timeMouseDown=0; // last mouse down time
int lastX=0,lastY=0; // last x and y

public boolean mouseDown(Event event, int x, int y){


/*
** check for double click
*/
long currentTime = event.when;
if ((lastX==x) && (lastY==y) &&
((event.when-timeMouseDown) < dClkRes)) {
System.out.println("double click " + currentTime);
return false;
}
else {
//single click action could be added here
System.out.println("simple click " + currentTime);
timeMouseDown = event.when;
lastX=x;
lastY=y;
}
return true;
}
}

[JDK11]

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

Detect a double click versus a simple click 96


Real's HowTo PDF version

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

Detect the mouse button used when clicking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0236.html

[JDK11]

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

public class d extends Applet


implements MouseListener {

public void init() {


this.addMouseListener(this);
}

public void paint(Graphics g) {


g.drawString("Click here", 10,10);
}

public void mousePressed(MouseEvent e) {}


public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {
switch(e.getModifiers()) {
case InputEvent.BUTTON1_MASK: {
System.out.println("That's the LEFT button");
break;
}
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;
}

Detect the mouse button used when clicking 97


Real's HowTo PDF version

}
}
}

Exit an application from a menu (single exit point)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0276.html

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

public class ExitFromMenu extends Frame implements ActionListener {


Menu m = new Menu("Exit From Here");

ExitFromMenu() {
super("");
MenuBar mb = new MenuBar();

mb.add(m);
MenuItem m1 = m.add(new MenuItem("Exit",
new MenuShortcut(KeyEvent.VK_X)));
m1.setActionCommand("Exit");
m.addActionListener(this);

setMenuBar(mb);

addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
// unique exit point
System.out.println("Bye.");
System.exit(0);
}
}
);
add(new Label
("You can quit by clicking on the 'X'"),"South");
add(new Label
("You can quit by clicking on the menu item 'Exit'"),"Center");
add(new Label
("You can quit with the MenuShortcut 'ctrl-x'"),"North");
setSize(300, 300);
show();
}

public void actionPerformed(ActionEvent evt) {


String what = evt.getActionCommand();

if (what.equals("Exit"))

Exit an application from a menu (single exit point) 98


Real's HowTo PDF version

processEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));


}

static public void main(String[] args) {


new ExitFromMenu();
}
}

Trigger a click on a Button


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

Trigger a click on a Button 99


Real's HowTo PDF version

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

Display a TIF
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0605.html

The regular JDK can only deal with JPG, GIF, BMP or PNG file with the package ImageIO, see this HowTo.

To deal with TIF file, you must use the JAI (Java Advanced Imaging) package.

This example will display a given TIF file. It will also display other types (JPG,...) by detecting the type.

import javax.media.jai.PlanarImage;
import com.sun.media.jai.codec.ByteArraySeekableStream;
import com.sun.media.jai.codec.ImageCodec;

Display a TIF 100


Real's HowTo PDF version

import com.sun.media.jai.codec.ImageDecoder;
import com.sun.media.jai.codec.SeekableStream;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.awt.Image;
import java.awt.image.RenderedImage;

import javax.swing.JOptionPane;
import javax.swing.JLabel;
import javax.swing.ImageIcon;

public class ImageViewer {

static Image load(byte[] data) throws Exception{


Image image = null;
SeekableStream stream = new ByteArraySeekableStream(data);
String[] names = ImageCodec.getDecoderNames(stream);
ImageDecoder dec =
ImageCodec.createImageDecoder(names[0], stream, null);
RenderedImage im = dec.decodeAsRenderedImage();
image = PlanarImage.wrapRenderedImage(im).getAsBufferedImage();
return image;
}

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


String path;
if (args.length==0) {
path = JOptionPane.showInputDialog(null, "Image Path",
"c:/applications/sidebar.tif");
}
else {
path = args[0];
}
FileInputStream in = new FileInputStream(path);
FileChannel channel = in.getChannel();
ByteBuffer buffer = ByteBuffer.allocate((int)channel.size());
channel.read(buffer);
Image image = load(buffer.array());
// make sure that the image is not too big
// scale with a width of 500
Image imageScaled =
image.getScaledInstance(500, -1, Image.SCALE_SMOOTH);
//
System.out.println("image: " + path + "\n" + image);
//
JOptionPane.showMessageDialog(null, new JLabel(
new ImageIcon( imageScaled )) );
}
}

The JAI package is composed of 2 jars : jai_core.jar and jai_codec.jar

Display a TIF 101


Real's HowTo PDF version

http://java.sun.com/javase/technologies/desktop/media/jai/
https://jai.dev.java.net/#Downloads

To write a TIF file, see this HowTo

Convert a multi-page TIF into single-page TIF


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0535.html

Tagged Image File Format (abbreviated TIFF) is a file format for mainly storing images, including
photographs and line art. TIFF was originally created as an attempt to get desktop scanner vendors of the
mid-1980's to agree on a common scanned image file format, rather than have each company promulgate its
own proprietary format.

This HowTo takes a multi-page TIF (from a FAX) and convert it into many single-pages TIF.

This is done with the JAI (Java Advance Image) package.

http://java.sun.com/products/java-media/jai/index.jsp

>
import java.io.*;

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

import java.awt.image.RenderedImage;
import javax.media.jai.RenderedOp;
import javax.media.jai.JAI;
import java.awt.image.renderable.ParameterBlock;

public class TestTiff {

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


new TestTiff().doitJAI();
}

public void doitJAI() throws IOException {


FileSeekableStream ss = new FileSeekableStream("d:/multi.tif");
ImageDecoder dec = ImageCodec.createImageDecoder("tiff", ss, null);
int count = dec.getNumPages();
TIFFEncodeParam param = new TIFFEncodeParam();
param.setCompression(TIFFEncodeParam.COMPRESSION_GROUP4);
param.setLittleEndian(false); // Intel

Convert a multi-page TIF into single-page TIF 102


Real's HowTo PDF version

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) multi-purpose graphic utility.

http://www.irfanview.com/

To do a TIF conversion, use this command line :

C:\IrfanView\i_view32" d:\multi.tif /extract=(d:\,tif) /killmesoftly

irfanview is an amazing software when it comes to transform a graphic format to another one. You can use it
from a command line or from a GUI.

See also : Convert many single-page TIF into one multi-page TIF

Convert many single-page TIF into one multi-page TIF


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-convert-many-single-tif-into-one-multiple-page-tif.html

This HowTo takes a list of single-page TIF and convert them into one multi-page TIF.

This is done with the JAI (Java Advance Image) package.

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

import javax.media.jai.NullOpImage;

Convert many single-page TIF into one multi-page TIF 103


Real's HowTo PDF version

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

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

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 multi-page TIF into single-page TIF

Convert an Image to a BufferedImage


Current version of this HowTo :

Convert an Image to a BufferedImage 104


Real's HowTo PDF version

http://www.rgagnon.com/javadetails/../javadetails/java-0601.html

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

public class ImageUtils {

public static BufferedImage imageToBufferedImage(Image im) {


BufferedImage bi = new BufferedImage
(im.getWidth(null),im.getHeight(null),BufferedImage.TYPE_INT_RGB);
Graphics bg = bi.getGraphics();
bg.drawImage(im, 0, 0, null);
bg.dispose();
return bi;
}

public static BufferedImage readImageFromFile(File file)


throws IOException
{
return ImageIO.read(file);
}

public static void writeImageToPNG


(File file,BufferedImage bufferedImage)
throws IOException
{
ImageIO.write(bufferedImage,"png",file);
}

public static void writeImageToJPG


(File file,BufferedImage bufferedImage)
throws IOException
{
ImageIO.write(bufferedImage,"jpg",file);
}
}

You need to do something to transform an Image to BufferedImage. But since BufferedImage extends Image,
so there isn't a back-conversion, it's not needed.

Detect if a TIF is blank


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0631.html

Detect if a TIF is blank 105


Real's HowTo PDF version

import javax.media.jai.PlanarImage;
import com.sun.media.jai.codec.ByteArraySeekableStream;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageDecoder;
import com.sun.media.jai.codec.SeekableStream;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.PixelGrabber;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;

/**
* This utility loads a given TIF and try to detect if it's
* blank or not.
*
* We create in-memory 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/java-media/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 =

Detect if a TIF is blank 106


Real's HowTo PDF version

ImageCodec.createImageDecoder(names[0], stream, null);


RenderedImage im = dec.decodeAsRenderedImage();
image = PlanarImage.wrapRenderedImage(im).getAsBufferedImage();
// scale-down 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);
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);

Detect if a TIF is blank 107


Real's HowTo PDF version

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

Convert TIF to PDF


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0645.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 letter-page dimension.

Convert TIF to PDF 108


Real's HowTo PDF version

import java.io.FileOutputStream;

import com.lowagie.text.Document;
import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfWriter;
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();

Convert TIF to PDF 109


Real's HowTo PDF version

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

Convert TIF to JPG


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-convert-tif-to-jpg.html

You need the Java Advanced Imaging (JAI) API.

http://java.sun.com/javase/technologies/desktop/media/jai/

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.awt.image.RenderedImage;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import com.sun.media.jai.codec.SeekableStream;
import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.TIFFDecodeParam;
import com.sun.media.jai.codec.ImageDecoder;
import 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);

Convert TIF to JPG 110


Real's HowTo PDF version

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 Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Convert TIF to JPG 111


Date and Time
java-date

Have year on 4 digits from a Date object


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

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

int year = myDate.getYear() + 1900;

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

Get the current Date and Time


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

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

public class DateUtils {


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

public static String now() {


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

public static void main(String arg[]) {


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

Here some formatting possibilities available through the SimpleDateFormat class.

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

Date and Time 112


Real's HowTo PDF version

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.

Compute days between 2 dates


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

Get the current Date and Time 113


Real's HowTo PDF version

java.text.SimpleDateFormat sdf =
new java.text.SimpleDateFormat("yyyyMMdd");
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); // 2008-08-01
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()));
}

Compute days between 2 dates 114


Real's HowTo PDF version

/*
* output :
* 921 day(s) between 20080801 and 20110208
*/
}

Get the number of days in a month


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

public static int daysInMonth(GregorianCalendar c) {


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

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

calObject.getActualMaximum(calobject.DAY_OF_MONTH)

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

gregCalObject.getActualMaximum(gregCalObject.DAY_OF_MONTH)

Validate a date
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0099.html

Using DateFormat

import java.text.*;

public class DateUtils {


public static boolean isValidDateStr(String date) {
try {
DateFormat df =

Get the number of days in a month 115


Real's HowTo PDF version

DateFormat.getDateInstance
(DateFormat.SHORT); // YYYY-MM-DD
df.setLenient(false); // this is important!
df.parse(date);
}
catch (ParseException e) {
return false;
}
catch (IllegalArgumentException e) {
return false;
}
return true;
}

public static void main(String[] args) {


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

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


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

Using SimpleDateFormat

package com.rgagnon.howto;

import java.text.*;

public class DateUtils {


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

Validate a date 116


Real's HowTo PDF version

public static void main(String[] args) {


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

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


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

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

Determine the day of the week


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

For the day of the week for today :

GregorianCalendar newCal = new GregorianCalendar( );


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

Validate a date 117


Real's HowTo PDF version

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

Add/Substract Day/Month/Year to a Date


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

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

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("yyyy-MM-dd");
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 : 1999-01-20
* Date + 20 days is : 1999-02-09
*/
}
}

To substract, simply use a negative argument.

Determine the day of the week 118


Real's HowTo PDF version

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("yyyy-MM-dd");
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 : "
+ 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 : 1999-01-20
* Date roll down 1 month : 1999-12-20
* Date is : 1999-01-20
* Date minus 1 month : 1998-12-20
*/
}
}

Get the correct TimeZone on DateFormat


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

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

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


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

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


Real's HowTo PDF version

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


df.getTimeZone.getID());

Simply format a date as "YYYYMMDD"


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

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

public static String getStrDate(GregorianCalendar c) {


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

Thanks to Vladimir Garmaev for the bug fix

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

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

public class TestDate {


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

Compare 2 dates
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0104.html

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

public class TestDate {

Get the correct TimeZone on DateFormat 120


Real's HowTo PDF version

public static void main(String args[]){


String DATE_FORMAT = "yyyy-MM-dd";
java.text.SimpleDateFormat sdf =
new java.text.SimpleDateFormat(DATE_FORMAT);
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
// remember months are zero-based : 0 jan 1 feb ...
c1.set(1999, 11 , 31);
c2.set(1999, 0 , 30);

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

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

Parse a String to obtain a Date/GregorianCalendar object


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

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

public class DateUtils {

public static Calendar parseTimestamp(String timestamp)


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

Compare 2 dates 121


Real's HowTo PDF version

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


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

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

Use System time to generate unique ID


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0385.html

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

public class UniqueID {


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

See also this HowTo

Get the day name


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

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

public class GetDayName {

Parse a String to obtain a Date/GregorianCalendar object 122


Real's HowTo PDF version

public static void main(String[] args) {


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

public static String sayDayName(Date d) {


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

An alternate way :

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

public class GetDayName {

public static void main(String[] args) {


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

Find the date format pattern


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

import java.text.*;
import java.util.*;
public class Dtest {
public static void main(String args[]) {

Get the day name 123


Real's HowTo PDF version

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

Get a julian date


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

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

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

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

Find the date format pattern 124


Real's HowTo PDF version

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


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

/**
* Converts a Julian day to a calendar date
* ref :
* Numerical Recipes in C, 2nd ed., Cambridge University Press 1992
*/
public static int[] fromJulian(double injulian) {
int jalpha,ja,jb,jc,jd,je,year,month,day;
double julian = injulian + HALFSECOND / 86400.0;
ja = (int) 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,

Get a julian date 125


Real's HowTo PDF version

today.get(Calendar.DATE)});
System.out.println("Julian date for today : " + todayJulian);
results = fromJulian(todayJulian);
System.out.println
("... back to calendar : " + results[0] + " " + results[1]
+ " " + results[2]);

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

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

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

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

A variation of this idea is to used the first four digits for the year and 3 digits for day-of-year, 17-July-1998
will be represented by 1998221.

This is a very simple format which can be manipulated easily from Java.

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

public class DateUtils {


private DateUtils() { }

public static Date getDateFromJulian7(String julianDate)


throws ParseException
{
return new SimpleDateFormat("yyyyD").parse(julianDate);
}

Get a julian date 126


Real's HowTo PDF version

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

Calculate the age


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

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

public class CalcAge {

public static void main(String [] args) {


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

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


Calendar cal = new GregorianCalendar(y, m, d);
Calendar now = new GregorianCalendar();
int res = now.get(Calendar.YEAR) - cal.get(Calendar.YEAR);
if((cal.get(Calendar.MONTH) > now.get(Calendar.MONTH))
|| (cal.get(Calendar.MONTH) == now.get(Calendar.MONTH)

Calculate the age 127


Real's HowTo PDF version

&& cal.get(Calendar.DAY_OF_MONTH) > now.get(Calendar.DAY_OF_MONTH)))


{
res--;
}
return res;
}
}

Format a duration in milliseconds into a human-readable format


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

public final static long ONE_DAY = ONE_HOUR * 24;

private TimeUtils() {
}

/**
* converts time (in milliseconds) to human-readable 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" : "")

Format a duration in milliseconds into a human-readable format 128


Real's HowTo PDF version

.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 human-readable 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 {
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));

Format a duration in milliseconds into a human-readable format 129


Real's HowTo PDF version

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 human-readable format
* "<dd:>hh:mm:ss"
*/
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)

Format a duration in milliseconds into a human-readable format 130


Real's HowTo PDF version

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

Get the atomic time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0589.html

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

List of available time servers : http://tf.nist.gov/tf-cgi/servers.cgi

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

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

public final class DateUtils {


// NIST, Boulder, Colorado (time-a.timefreq.bldrdoc.gov)
// public static final String ATOMICTIME_SERVER="132.163.4.101";
// NIST, Gaithersburg, Maryland (time-a.nist.gov)
// public static final String ATOMICTIME_SERVER="129.6.15.28";
// NIST, Gaithersburg, Maryland (time-c.nist.gov)
public static final String ATOMICTIME_SERVER="129.6.15.30";
public static final int ATOMICTIME_PORT = 13;

public final static GregorianCalendar getAtomicTime() throws IOException{


BufferedReader in = null;
Socket conn = null;

try {
conn = new Socket(ATOMICTIME_SERVER, ATOMICTIME_PORT);

Get the atomic time 131


Real's HowTo PDF version

in = new BufferedReader
(new InputStreamReader(conn.getInputStream()));

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

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


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

// deals with the timezone and the daylight-saving-time (you may need to adjust this)
// here i'm using "EST" for Eastern Standart Time (to support Daylight Saving Time)
TimeZone tz = TimeZone.getTimeZone("EST"); // or .getDefault()
int gmt = (tz.getRawOffset() + tz.getDSTSavings()) / 3600000;
System.out.println("DEBUG 2 : " + 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(); }
if (conn != null) { conn.close(); }
}
}

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


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

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

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

| | | | | | | | |

Get the atomic time 132


Real's HowTo PDF version

These are the last + | | || | | | |


five digits of the | | || | | | |
Modified Julian Date | | || | | | |
| | || | | | |
Year, Month and Day <----+ | || | | | |
| || | | | |
Hour, minute, and second of the <-+ || | | | |
current UTC at Greenwich. || | | | |
|| | | | |
DST - Daylight Savings Time code <------+ | | | | |
00 means standard time(ST), 50 means DST | | | | |
99 to 51 = Now on ST, goto DST when local | | | | |
time is 2:00am, and the count is 51. | | | | |
49 to 01 = Now on DST, goto ST when local | | | | |
time is 2:00am, and the count is 01. | | | | |
| | | | |
Leap second flag is set to "1" when <-----+ | | | |
a leap second will be added on the last | | | |
day of the current UTC month. A value of | | | |
"2" indicates the removal of a leap second. | | | |
| | | |
Health Flag. The normal value of this | <-+
| |
flag is 0. Positive values mean there may | | |
be an error with the transmitted time. | | |
| | |
The number of milliseconds ACTS is advancing <-+ | |
the time stamp, to account for network lag. | |
| |
Coordinated Universal Time from the National <--------+ |
Institute of Standards & Technology. |
|
The instant the "*" appears, is the exact time. <------------+
*/
}

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

Get a date interval


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

Get a date interval 133


Real's HowTo PDF version

import java.util.*;

public class DateUtils {

public enum IntervalType { Month, Week }

private DateUtils() { }

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);
}
}
return new Calendar[] { startDate, endDate };
}

public static void main(String[] args) {


try {

Get a date interval 134


Real's HowTo PDF version

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

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 month (relative today)
2008-06-01
2008-06-30
** previous week (relative today)
2008-06-30
2008-07-06
** previous month (relative jan 1, 2007)
2006-12-01
2006-12-31
** previous week (relative jan 1, 2007)
2006-12-25
2006-12-31
*/
}

Determine if a given hour is between an interval


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0624.html

Determine if a given hour is between an interval 135


Real's HowTo PDF version

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:00-14:26?
* false
*
*/
}
}

Determine if a given hour is between an interval 136


Real's HowTo PDF version

Set the computer clock (JNI)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0285.html

Define the following prototype in the header file

JNIEXPORT void JNICALL Java_JavaHowTo_setSystemTime


(JNIEnv *, jobject, jshort, jshort);

the JNI function

JNIEXPORT void JNICALL Java_JavaHowTo_setSystemTime


(JNIEnv *env, jobject obj, jshort hour, jshort minutes) {

SYSTEMTIME st;

GetLocalTime(&st);
st.wHour = hour;
st.wMinute = minutes;
SetLocalTime(&st);
}

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

Set the computer clock (JNI) 137


Real's HowTo PDF version

Get unique numerical id based on the system time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0385.html

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

public class UniqueID {


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

See also this HowTo

Get the month (or day) name (localized)


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

Get unique numerical id based on the system time 138


Real's HowTo PDF version

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

Detect a leap year


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

Get the month (or day) name (localized) 139


Real's HowTo PDF version

// using a Calendar
public static boolean isLeap1(int year) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
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[] args) {


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

Written and compiled Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Detect a leap year 140


Environment
java-env

Read environment variables from an application


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0150.html

NOTE: JDK1.5 or better provides a simpler way to achieve this, see this HowTo.

JDK up to 1.4
Start the JVM with the "-D" switch to pass properties to the application and read them with the
System.getProperty() method.

SET myvar=Hello world


SET myothervar=nothing
java -Dmyvar="%myvar%" -Dmyothervar="%myothervar%" myClass

then in myClass

String myvar = System.getProperty("myvar");


String myothervar = System.getProperty("myothervar");

If you don't know in advance, the name of the variable to be passed to the JVM, then there is no 100% Java
way to retrieve them.

One approach (not the easiest one), is to use a JNI call to fetch the variables, see this HowTo.

A more low-tech way, is to launch the appropriate call to the operating system and capture the output. The
following snippet puts all environment variables in a Properties class and display the value the TEMP
variable.
import java.io.*;
import java.util.*;

public class ReadEnv {


public static Properties getEnvVars() throws Throwable {
Process p = null;
Properties envVars = new Properties();
Runtime r = Runtime.getRuntime();
String OS = System.getProperty("os.name").toLowerCase();
// System.out.println(OS);
if (OS.indexOf("windows 9") > -1) {
p = r.exec( "command.com /c set" );

Environment 141
Real's HowTo PDF version

}
else if ( (OS.indexOf("nt") > -1)
|| (OS.indexOf("windows 2000") > -1 )
|| (OS.indexOf("windows xp") > -1) ) {
// thanks to JuanFran for the xp fix!
p = r.exec( "cmd.exe /c set" );
}
else {
// 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)

Read environment variables from an application 142


Real's HowTo PDF version

|| (OS.indexOf("windows 20") > -1 ) // better,


// since no other OS would
// return "windows"
|| (OS.indexOf("windows xp") > -1) ) {

I started with "windows 200" but thought "what the hell" and made it "windows 20" to lengthen its longivity.
You could push it further and use "windows 2," I suppose. The only thing to watch out for is to not overlap
with "windows 9."

On Windows, pre-JDK 1.2 JVM has trouble reading the Output stream directly from the SET command, it
never returns. Here 2 ways to bypass this behaviour.

First, instead of calling directly the SET command, we use a BAT file, after the SET command we print a
known string. Then, in Java, when we read this known string, we exit from loop.

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

Read environment variables from an application 143


Real's HowTo PDF version

...

// then read back the file as a Propêrties


Properties p = new Properties();
p.load(new FileInputStream("envvar.txt"));

Thanks to JP Daviau

// UNIX
public Properties getEnvironment() throws java.io.IOException {
Properties env = new Properties();
env.load(Runtime.getRuntime().exec("env").getInputStream());
return env;
}

Properties env = getEnvironment();


String myEnvVar = env.get("MYENV_VAR");

To read only one variable :


// NT version , adaptation for other OS is left as an exercise...
Process p = Runtime.getRuntime().exec("cmd.exe /c echo %MYVAR%");
BufferedReader br = new BufferedReader
( new InputStreamReader( p.getInputStream() ) );
String myvar = br.readLine();
System.out.println(myvar);

Java's System properties contains some useful informations about the environment, for example, the TEMP
and PATH environment variables (on Windows).
public class ShowSome {
public static void main(String args[]){
System.out.println("TEMP : "
+ System.getProperty("java.io.tmpdir"));
System.out.println("PATH : "
+ System.getProperty("java.library.path"));
System.out.println("CLASSPATH : "
+ System.getProperty("java.class.path"));
System.out.println("SYSTEM DIR : " +
System.getProperty("user.home")); // ex. c:\windows on Win9x
System.out.println("CURRENT DIR: "
+ System.getProperty("user.dir"));
}
}

Here some tips from H. Ware about the PATH on different OS.

PATH is not quite the same as library path. In unixes, they are completely different---the libraries typically
have their own directories.

System.out.println("the current value of PATH is: {" +


p.getProperty("PATH")+"}");

Read environment variables from an application 144


Real's HowTo PDF version

System.out.println("LIBPATH: {" +
System.getProperty("java.library.path")+"}");

gives

the current value of PATH is:


{/home/hware/bin:/usr/local/bin:/usr/xpg4/bin:/opt/SUNWspro/bin:
/usr/ucb:/bin:/usr/bin:/home/hware/linux-bin:/usr/openwin/bin/:
/usr/local/games:/usr/ccs/lib/:/usr/new:/usr/sbin/:/sbin/:
/usr/openwin/lib:/usr/X11/bin:/usr/bin/X11/:/usr/local/bin/X11:
/usr/bin/pbmplus:/usr/etc/:/usr/dt/bin/:/usr/lib:
/usr/lib/nis:/usr/share/bin:/usr/share/bin/X11:
/home/hware/work/cdk/main/cdk/../bin:.}
LIBPATH:
{/usr/lib/j2re1.3/lib/i386:/usr/lib/j2re1.3/lib/i386/native_threads:
/usr/lib/j2re1.3/lib/i386/client:/usr/lib/j2sdk1.3/lib/i386:/usr/lib:/lib}

on my linux workstation. (java added all those except /lib and /usr/lib). But these two lines aren't the same on
window either:

This system is windows nt

the current value of PATH is:


{d:\OrbixWeb3.2\bin;D:\jdk1.3\bin;c:\depot\cdk\main\cdk\bin;c:\depot\
cdk\main\cdk\..\bin;d:\OrbixWeb3.2\bin;D:\Program
Files\IBM\GSK\lib;H:\pvcs65\VM\win32\bin;c:\cygnus
\cygwin-b20\H-i586-cygwin32\bin;d:\cfn\bin;D:\orant\bin;
C:\WINNT\system32;C:\WINNT;
d:\Program Files\Symantec\pcAnywhere;
C:\Program Files\Executive Software\DiskeeperServer\;}
LIBPATH:
{D:\jdk1.3\bin;.;C:\WINNT\System32;C:\WINNT;D:\jdk1.3\bin;
c:\depot\cdk\main\cdk\bin;c:\depot\cdk\main\cdk\..\bin;
d:\OrbixWeb3.2\bin;D:\Program Files\IBM\GSK\lib;
H:\pvcs65\VM\win32\bin;c:\cygnus\cygwin-b20\H-i586-cygwin32\bin;d:\cfn\bin;
D:\orant\bin;C:\WINNT\system32;
C:\WINNT;C:\Program Files\Dell\OpenManage\ResolutionAssistant\Common\bin;
d:\Program Files\Symantec\pcAnywhere;
C:\Program Files\Executive Software\DiskeeperServer\;}

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

Belorussian translation

Read environment variables (JDK1.5)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0466.html

Read environment variables (JDK1.5) 145


Real's HowTo PDF version

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

Read environment variables (JNI)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0460.html

For some odd reasons, the getenv() method was removed from the JDK. Rumors is that a mechanism to
retrieve an environment will be back in JDK1.5 (see this HowTo). But for now, you can use -D switch to
retrieve named environment variable and pass them to the JVM (see this HowTo) or use this JNI routine :

JNIEXPORT jstring JNICALL JavaHowTo_getenv


(JNIEnv *env, jclass c, jstring jname){
if ( jname == NULL ) {
return NULL ;
}
const char *name =
(*env)->GetStringUTFChars(env, jname, (jboolean *)NULL) ;
const char *value = getenv(name) ;
(*env)->ReleaseStringUTFChars(env, jname, name) ;
return value ? (*env)->NewStringUTF(env, value) : NULL ;
}

NOTE : This is fine if the environment variable contains only regular 7-bit ASCII characters.

See also this HowTo.

Read environment variables (JNI) 146


Real's HowTo PDF version

Use a MAKE file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0158.html

# jMAKEFILE a MAKEFILE for JAVA development


# (Microsoft nMAKE)
# nmake /f j.makefile.mak doc
# to generate JAVADOC

.SUFFIXES: .class .java

JAVAHOME=c:\windev\jdk1.1.3
JAVAC= $(JAVAHOME)\bin\javac
PATH=$(JAVAHOME)\bin;$(PATH)
CLASSPATH=.;$(JAVAHOME)\lib\classes.zip;$(JSDKHOME)\lib\classes.zip
DEST=.
DOC=.
JAVA=$(JAVAHOME)\bin\java
JAVACFLAGS=-deprecation

.SUFFIXES: .java .class

.java.class:
$(JAVAC) -classpath $(CLASSPATH) $(JAVACFLAGS) $<

CLASSFILES = GetImage.class \
myCanvas.class

SOURCEFILES = GetImage.java \
myCanvas.java

# begin ---- JAR support ----------


JARFILE= theJAR.jar

$(JARFILE): $(CLASSFILES) $(SOURCEFILES)


jar cfm0 $(JARFILE) <<manifest.tmp $(CLASSFILES)
$(DATAFILES)
Name: GetImage.class
Java-Bean: False

Name: myCanvas.class
Java-Bean: True
<<
# end ---- JAR support ----------

all : $(JARFILE) $(CLASSFILES) doc

doc : $(CLASSFILES)

Use a MAKE file 147


Real's HowTo PDF version

javadoc -version -author -d $(DOC) $(SOURCEFILES)

install :
copy $CLASSESFILE $(DEST)

clean:
del $(CLASSFILES)

Detect the browser/JVM type


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0160.html

This HowTo is obsolete. Check this one instead : Detect browser type from an Applet
One way is to instanciate a known browser-specific method and catch the Exception if not found
import java.applet.*;

public class BrowserDetector extends Applet {


public void init() {
if ( isNetscape() )
System.out.println("This browser is a Netscape Browser.");
if ( isMicrosoft() )
System.out.println("This browser is a Microsoft Browser.");
}

public static boolean isNetscape() {


try {
Class.forName("netscape.applet.MozillaAppletContext");
}
catch (ClassNotFoundException e) {
System.out.println("This browser is not a Netscape Browser.");
return false;
}
return true;
}

public static boolean isMicrosoft() {


try {
Class.forName("com.ms.applet.GenericAppletContext");
}
catch (ClassNotFoundException e) {
System.out.println("This browser is not a Microsoft Browser.");
return false;
}
return true;
}
}

Or by examining the string representation of the getAppletContext() method

Detect the browser/JVM type 148


Real's HowTo PDF version

String theBrowser = "APPLICATION";


String appletContext = getAppletContext().toString();
if (appletContext.startsWith("sun.applet.AppletViewer"))
theBrowser = "APPLETVIEWER";
else if (appletContext.startsWith("netscape.applet."))
theBrowser = "NETSCAPE";
else if (appletContext.startsWith("com.ms.applet."))
theBrowser = "MICROSOFT";
else if (appletContext.startsWith("sunw.hotjava.tags.TagAppletPanel"))
theBrowser = "HOTJAVA";
else if (appletContext.startsWith( "sun.plugin.navig.win32.AppletPlugin"))
theBrowser = "NETSCAPEPLUGIN";
else if (appletContext.startsWith( "sun.plugin.ocx.ActiveXApplet"))
theBrowser = "MICROSOFTPLUGIN;
else if (appletContext.startsWith
( "sun.plugin.viewer.context.IExplorerAppletContext")
theBrowser = "MICROSOFTPLUGINJRE1.4;

For an application, by looking at the string representation of the getDefaultToolkit() method, we detect the
JVM type

String theJVM = "";


String toolkit = Toolkit.getDefaultToolkit().toString();

if (theBrowser.equals("APPLICATION") {
if (toolkit.startsWith( "sun.awt.windows.WToolkit"))
theJVM = "JAVA";
else if (toolkit.startsWith( "com.ms.awt.WToolkit"))
theJVM = "JVIEW";
}

For example, our MyApplet.class exists in three versions. One is using Microsoft-specific classes, the other is
a JDK1.1 applet and finally a version for JDK102-only browser. The idea is to put all the required classes in
an ARCHIVE file. By using a javascript entities, we decide which archive to use. During layout time, the
javascript entity is remplaced by the right archive name.

<HTML></HTML><HEAD>
<SCRIPT>
function isBrowser(b,v) {
browserOk = false;
versionOk = false;
browserOk = (navigator.appName.indexOf(b) != -1);
versionOk = (v <= parseInt(navigator.appVersion));
return browserOk && versionOk;
}

archiveToBeUsed = "java102.jar";

if (isBrowser("Microsoft", 4)) {
archiveToBeUsed = "ie4.jar";
}
else {

Detect the browser/JVM type 149


Real's HowTo PDF version

if isBrowser("Netscape", 4) {
archiveToBeUsed = "n4.jar";
}
}

</SCRIPT></HEAD><BODY>
<APPLET CODE ="MyApplet.class"
HEIGHT=100
WIDTH=400
ARCHIVE=&{archiveToBeUsed}; >
</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.

Fix the "Wrong magic number" error message


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0163.html

The "magic number" is represented by the first few bytes of a given file. It is used to identified the file type.

For Java classes, the magic number is 0xCAFEBABE (you can verify this by viewing a class file with
hexadecimal editor or the DOS Debug utility). This is used by the browser JVM as a quick check of whether
the called file is really a Java class.

If the message is displayed and you are sure that you have uploaded a "real" class to web server then it's
probably because the FTP download has been done in TEXT mode instead of BINARY so the resulting file on
the server is corrupted.

Use a precompiler "à la C" with Java


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0164.html

Open source packages

Check this list of what is available.

Also take a look at JEnable

Fix the "Wrong magic number" error message 150


Real's HowTo PDF version

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>

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

Use a precompiler "à la C" with Java 151


Real's HowTo PDF version

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

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.

Determine what are the classes actually used


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0165.html

In Netscape

1. Open the Java console


2. Press "9" to set the Debug level
3. Execute your applet.
4. Check the console and take note of the loaded classes.

In application

java -verbose:class MyApp

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

Use a precompiler "à la C" with Java 152


Real's HowTo PDF version

Set the memory available to the JVM


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

Generate the Javadoc "en français"


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0437.html

The javadoc utility uses the regular Java mechanism to internationalize its output. The tools.jar in the lib
directory contains the resource bundle standard.properties used by Javadoc to generated the labels. To add a
new language, you need to create the appropriate resource bundle, in our case for french, we need a file called
standard_fr.properties.

The new file must be in the package com.sun.tools.doclets.standard.resources.

Extract from tools.jar, the standard.properties files (keep the directory structure). Copy it under the name
standard_fr.properties. Translate it (or you can download my "incomplete" version here).

[standard.properties (extract)]

doclet.Window_Split_Index={0}\: {1}-Index
doclet.Packages=Packages
doclet.SerialData=Serial Data\:
doclet.Since=Since\:
doclet.Warn_inline_taglet=Inline tag {0} should only be used with a {1}.
doclet.ClassUse_Subinterface=Subinterfaces of {0} in {1}
doclet.Frame_Version=Frame version
doclet.Generated_Docs_Untitled=Generated Documentation (Untitled)

Set the memory available to the JVM 153


Real's HowTo PDF version

[standard_fr.properties (extract)]

doclet.Window_Split_Index={0}\: {1}-Index
doclet.Packages=Paquetages
doclet.SerialData=Donn\u00E9e s\u00E9rialis\u00E9e\:
doclet.Since=Depuis\:
doclet.Warn_inline_taglet=Inline tag {0} should only be used with a {1}.
doclet.ClassUse_Subinterface=Sous-interfaces de {0} dans {1}
doclet.Frame_Version=Version avec cadres
doclet.Generated_Docs_Untitled=Documentation g\u00E9n\u00E9r\u00E9e

Once everything translated, put your standard_fr.properties into the tools.jar making sure that the file is
located in the right package (along standard.properties in com.sun.tools.doclets.standard.resources).

To generate in french, use the -locale switch on the command line

javadoc -locale fr ....

NOTE : Make sure the -locale switch is the first one.

Using Ant,

<javadoc
locale="fr"
sourcefiles="c:/client/Client.java"
destdir="javadoc/Client"
author="true"
version="true"
use="true"
private="true"
windowtitle="Client">
<doctitle><![CDATA[<h1>Client</h1>]]></doctitle>
<bottom><![CDATA[<i>Copyright &#169; 2003 Real's Howto.</i>]]></bottom>
</javadoc>

Use JDK1.5 new features


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0462.html

• Download the JDK1.5 and install it.


• From a shell, type
&GT; java -version

The response should be something like

java version "1.5.0-beta"

Generate the Javadoc "en français" 154


Real's HowTo PDF version

Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta-b32c)


JAVA HOTSPOT(TM) CLIENT VM (BUILD 1.5.0-BETA-B32C, MIXED MODE)

On Windows, if you have a "file not found" message, it's because the JVM can't be found through the
PATH. Do it again but with the complete path (if the path contains spaces, make sure to use quotes!) :

&GT; "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):
&GT; "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

Check the class version


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0544.html

The first 4 bytes are a magic number, 0xCAFEBABe, to identify a valid class file then the next 2 bytes
identify the class format version (major and minor).

Possible major/minor value :

major minor Java platform version


45 3 1.0
45 3 1.1
46 0 1.2
47 0 1.3
48 0 1.4
49 0 1.5
50 0 1.6
51 0 1.7
52 0 1.8

import java.io.*;

public class ClassVersionChecker {


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

Use JDK1.5 new features 155


Real's HowTo PDF version

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.

Get the system properties or the JVM uptime


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0549.html

The RuntimeMXBean defines several convenient methods for accessing system properties about the Java
virtual machine.

Check the class version 156


Real's HowTo PDF version

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

Detect if running in a 64bit JVM


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0565.html

public static boolean is64BitVM() {


String bits = System.getProperty("sun.arch.data.model", "?");
if (bits.equals("64") {
return true;
}
if (bits.equals("?") {
// probably sun.arch.data.model isn't available
// maybe not a Sun JVM?
// try with the vm.name property
return

Get the system properties or the JVM uptime 157


Real's HowTo PDF version

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

Set the default JVM type


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0566.html

If you type, in a Shell

> java -version

you get

java version "1.5.0"


Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode, sharing)

The default JVM with a JIT (Just-In-Time compiler) for a "client" mode is used. The other available mode is
"server".

From the Hot Spot FAQ at http://java.sun.com/docs/hotspot/HotSpotFAQ.html#compiler_types.

What's the difference between the -client and -server systems?

These two systems are different binaries. They are essentially two different compilers (JITs)interfacing to the
same runtime system. The client system is optimal for applications which need fast startup times or small
footprints, the server system is optimal for applications where the overall performance is most important. In
general the client system is better suited for interactive applications such as GUIs. Some of the other
differences include the compilation policy,heap defaults, and inlining policy.

Where do I get the server and client systems?

Client and server systems are both downloaded with the 32-bit Solaris and Linux downloads. For 32-bit
Windows, if you download the JRE, you get only the client, you'll need to download the SDK to get both
systems.

For 64-bit, only the server system is included. On Solaris, the 64-bit JRE is an overlay on top of the 32-bit
distribution. However, on Linux and Windows, it's a completely separate distribution. The default setting is
defined the file jvm.cfg.

Detect if running in a 64bit JVM 158


Real's HowTo PDF version

On Debian GNU/Linux with Sun Java 1.5.0, the file is in /etc/java-1.5.0-sun.


On Windows, it's in C:\Program Files\Java\jre1.5.0\lib\i386.

A content like

-client KNOWN
-server KNOWN

defines the client as the default.

-server KNOWN
-client KNOWN

sets the server as the default.

Select a particular JRE from the command line


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0634.html

It's possible to have many JRE side-by-side 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

Set the default JVM type 159


Real's HowTo PDF version

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

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"

Get the PID (pure Java solution)


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

Select a particular JRE from the command line 160


Real's HowTo PDF version

The result is

For a Java-JNI solution, see this HowTo.

Get the PID (JNI solution)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0467.html

class JavaHowTo {
public native long getCurrentProcessId();
static {
System.loadLibrary("jni2");
}
}

public class JNIJavaHowTo {


public static void main(String[] args) {
JavaHowTo jht = new JavaHowTo();
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"

Get the PID (pure Java solution) 161


Real's HowTo PDF version

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 Java-only solution, see this HowTo

Set default value for Java property or JVM option (system wide)
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-set-java-properties-system-wide.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

Get the PID (JNI solution) 162


Real's HowTo PDF version

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/TSG-Desktop/html/plugin.html#gcexdd

Detect if running in debug mode


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-detect-if-running-in-debug-mode.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);
}
}

Configure Java deployment with properties


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-configure-java-deployment-with-properties.html

User level

The deployment.properties file is used for storing and retrieving deployment configuration properties
shown in the Java Control Panel. The properties are also used for customizing runtime behavior for both Java
Plug-in and Java Web Start.

Location of the deployment.properties :

• Windows - <User Application Data


Folder>\LocalLow\Sun\Java\Deployment\deployment.properties
• Linux - ${user.home}/.java/deployment/deployment.properties
• OS X - ~/Library/Application
Support/Oracle/Java/Deployment/deployment.properties

Set default value for Java property or JVM option (system wide) 163
Real's HowTo PDF version

On the Windows, <User Application Data Folder> is typically C:\Users\<your username>\AppData (or
%APPDATA%) which is hidden by default.

ref : Oracle Java documentation

List of possible deployment properties

#deployment.properties https://gist.githubusercontent.com/MyITGuy/9628895/raw/3727348918e036ba

# Security Tab
# Enable Java content in the browser
deployment.webjava.enabled=true
deployment.webjava.enabled.locked
# Security Level
deployment.security.level=MEDIUM
deployment.security.level.locked

# Advanced Tab
# Debugging\Enable tracing
deployment.trace=false
deployment.trace.locked
# Debugging\Enable logging
deployment.log=false
deployment.log.locked
# Debugging\Show applet lifecycle exceptions
deployment.javapi.lifecycle.exception=false
deployment.javapi.lifecycle.exception.locked
# Java console
deployment.console.startup.mode.locked
deployment.console.startup.mode=HIDE
# Default Java for browsers\Microsoft Internet Explorer
deployment.browser.vm.iexplorer=true
deployment.browser.vm.iexplorer.locked
# Default Java for browsers\Mozilla family
deployment.browser.vm.mozilla.locked
deployment.browser.vm.mozilla=false
# Java Plug-in\Enable the next-generation Java Plug-in (requires browser restart)
# This must be done by executing one of the following commands as an administrator:
# [Disable] - {JREInstallPath}\bin\ssvagent.exe -high -jpisetup -old
# [Enable] - {JREInstallPath}\bin\ssvagent.exe -high -jpisetup -new
# Shortcut Creation
deployment.javaws.shortcut=ASK_IF_HINTED
deployment.javaws.shortcut.locked
# JNLP File/MIME Association
deployment.javaws.associations=ASK_USER
deployment.javaws.associations.locked
# Application Installation
deployment.javaws.install=IF_HINT
deployment.javaws.install.locked
#JRE Auto-Download
deployment.javaws.autodownload=NEVER
deployment.javaws.autodownload.locked
# Security Execution Environment\Enable granting elevated access to signed apps

Configure Java deployment with properties 164


Real's HowTo PDF version

# aka. Allow user to grant permissions to signed content


deployment.security.askgrantdialog.show=true
deployment.security.askgrantdialog.show.locked
# Security Execution Environment\Enable granting elevated access to self-signed apps
deployment.security.askgrantdialog.notinca=true
deployment.security.askgrantdialog.notinca.locked
# Security Execution Environment\Show sandbox warning banner
deployment.security.sandbox.awtwarningwindow=true
deployment.security.sandbox.awtwarningwindow.locked
# Security Execution Environment\Allow user to accept JNLP security requests
deployment.security.sandbox.jnlp.enhanced=true
deployment.security.sandbox.jnlp.enhanced.locked
# Security Execution Environment\Don't prompt for client certificate selection when no certific
deployment.security.clientauth.keystore.auto=true
deployment.security.clientauth.keystore.auto.locked
# Security Execution Environment\Warn if site certificate does not match hostname
deployment.security.jsse.hostmismatch.warning=true
deployment.security.jsse.hostmismatch.warning.locked
# Security Execution Environment\Show site certificate from server even if it is valid
deployment.security.https.warning.show=false
deployment.security.https.warning.show.locked
# Mixed code (sandbox vs. trusted) security verification
deployment.security.mixcode=DISABLE
deployment.security.mixcode.locked
# Perform certificate revocation checks on
deployment.security.revocation.check=ALL_CERTIFICATES
deployment.security.revocation.check.locked
# Check for certificate revocation using
# Replaces Advanced Security Settings\Check certificates for revocation using Certificate Revoc
# [Certificate Revocation List (CRLs)] - ocsp=false, crl=true
# [Online Certificate Status Protocol (OCSP)] - ocsp=true, crl=false
# [Bot CRLs and OCSP] - ocsp=true, crl=true
deployment.security.validation.ocsp=true
deployment.security.validation.ocsp.locked
deployment.security.validation.crl=true
deployment.security.validation.crl.locked
# Advanced Security Settings\Use certificates and keys in browser keystore
deployment.security.browser.keystore.use=true
deployment.security.browser.keystore.use.locked
# Advanced Security Settings\Check certificates for revocation using Certificate Revocation Lis
# See Check for certificate revocation using
# Advanced Security Settings\Enable list of trusted publishers
deployment.security.pretrust.list=true
deployment.security.pretrust.list.locked
# Advanced Security Settings\Enable blacklist revocation check
deployment.security.blacklist.check=true
deployment.security.blacklist.check.locked
# Advanced Security Settings\Enable caching password for authentication
deployment.security.password.cache=true
deployment.security.password.cache.locked
# Advanced Security Settings\Enable online certifcate validation
deployment.security.revocation.check=NO_CHECK
deployment.security.revocation.check.locked
# Advanced Security Settings\Use SSL 2.0 compatible ClientHello format

Configure Java deployment with properties 165


Real's HowTo PDF version

deployment.security.SSLv2Hello=false
deployment.security.SSLv2Hello.locked
# Advanced Security Settings\Use SSL 3.0
deployment.security.SSLv3=true
deployment.security.SSLv3.locked
# Advanced Security Settings\Use TLS 1.0
deployment.security.TLSv1=true
deployment.security.TLSv1.locked
# Advanced Security Settings\Use TLS 1.1
deployment.security.TLSv1.1=false
deployment.security.TLSv1.1.locked
# Advanced Security Settings\Use TLS 1.2
deployment.security.TLSv1.2=false
deployment.security.TLSv1.2.locked
# Miscellaneous\Place Java icon in system tray
# Miscellaneous\Java Quick Starter
deployment.system.tray.icon=false
deployment.system.tray.icon.locked

# Screen: Your Java version is insecure. or Your Java version is out of date.
deployment.expiration.check.enabled=false
deployment.expiration.check.enabled.locked
#
deployment.capture.mime.types=true
deployment.capture.mime.types.locked

deployment.security.expired.warning=false
deployment.security.expired.warning.locked

deployment.user.security.exception.sites=C:\\WINDOWS\\Sun\\Java\\Deployment\\exception.sites
deployment.user.security.exception.sites.locked
# Java 7 Update 10
deployment.expiration.decision.10.10.2.locked
deployment.expiration.decision.10.10.2=later
deployment.expiration.decision.suppression.10.10.2.locked
deployment.expiration.decision.suppression.10.10.2=true
deployment.expiration.decision.timestamp.10.10.2.locked
deployment.expiration.decision.timestamp.10.10.2=2/28/2014 12\:1\:31

Example of a deployment.properties

#deployment.properties
deployment.webjava.enabled=true
deployment.security.level=MEDIUM
deployment.security.level.locked
deployment.user.security.exception.sites=c\:/Windows/Sun/Java/Deployment/exception.sites

The exception.sites file is a one URL per line list of sites that you want in the Exception Site List field
found in the Java Control Panel. Nothing else goes in this file.

Configure Java deployment with properties 166


Real's HowTo PDF version

System level

The deployment.config file is used for specifying the system-level deployment.properties in the
infrastructure. By default no deployment.config file exists, so no system-wide deployment.properties file
exists.

Possible location of the deployment.config :

• Windows - <Windows Directory>\Sun\Java\Deployment\deployment.config or


${deployment.java.home}\lib\deployment.config
• Linux - /etc/.java/deployment/deployment.config or
${deployment.java.home}/lib/deployment.config
• OS X - /Library/Application
Support/Oracle/Java/Deployment/deployment.config or
${deployment.java.home}/lib/deploy/deployment.config

The deployment.config file contains two properties: deployment.system.config and


deployment.system.config.mandatory.

The deployment.system.config property is the URL to the system (enterprise-wide) deployment.properties


file. This property can be used by system administrators to centrally administer or "lock-down" user-specific
configuration settings. For local files, use the file protocol in the URL, for example,
file:///C:/Windows/Sun/Java/Deployment/deployment.properties.

The deployment.system.config.mandatory property is a boolean. If set to true, the deployment.properties file


that is pointed to by the deployment.system.config property must be found and successfully loaded, otherwise,
nothing is allowed to run. If the property is set to false, an attempt is made to find and load the deployment.
properties file that is pointed to by the deployment.system.config property. If successful, the file is used,
otherwise, the file is ignored. The default for the deployment.system.config.mandatory property is false.

deployment.system.config=file\://ourserver.local/deploy/Sun/Java/Deployment/deployment.properti
deployment.system.config.mandatory=true

This example points to a deployment.properties file on a DFS path //ourserver.local/deploy/. Since the
property deployment.system.config.mandatory=true then if the deployment.properties file is not found, then
nothing is allowed to run.

Wrap a Java bean in a COM object (using Sun ActiveX bridge)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0045.html

The previous How-to was using a Microsoft utility to enable access to Java objects from a COM-aware
development tool. Sun provides a similar tool but you must package everything in a jar file and use the Beans

Configure Java deployment with properties 167


Real's HowTo PDF version

technology. The tool is called packager, written in Java, you execute it from the sun.beans.ole package. The
Java Plug-in 1.2 and the JDK1.2 must be installed on the system (for download, see Java Sun Web site).

Let's try it with this simple class :

package JavaCom;
public class JavaBeanSays {
private String _hello = "Hello World!";

public String getHello() {


return _hello ;
}

public void setHello(String s) {


_hello = s;
}
}

NOTE: This is not really a Bean but let's keep it simple!

The next step is to build a manifest file to identify the bean in the jar. Here it is (manifest.txt):

Name: JavaCom/JavaBeanSays
Java-Bean: true

NOTE: If no manifest is present all classes in the jar are treated as beans.

The JavaBeanSays class is in the directory JavaCom, the manifest.txt is the directory under it. From the
directory under (the one containing manifest.txt), we built the jar with :

jar cfm javacom.jar manifest.txt javacom\JavaBeanSays.class

NOTE: You can download my JavaCom.jar if you to proceed more rapidly.

The next step is to run the packager. You run it from the JDK installation directory. If the JDK is installed in
c:\dev\java\jdk1.2.1\ for example , you go there. And you start the packager with

bin\java.exe -cp jre\lib\rt.jar;jre\lib\jaws.jar sun.beans.ole.Packager

A wizard is started, you follow the 5 steps to create the "JavaBeans bridge for ActiveX" for the JavabeanSays
component.

The first step is to specify where is located the JavaCom.jar file. When selected, the wizard should list the
JavaCom.JavaBeanSays bean, press Next. The "ActiveX" name under which the beans will be seen is shown,
press Next (in VbScript, the beans suffix must be added to this name).

An output directory is needed, be careful because this directory name will be hard-coded in the generated files
(REG and TLB), you need to specify a valid directory name. The packager assume that a subdirectory bin is
present with the file beans.ocx in it. You can create it and then copy beans.ocx from the JRE\bin into it or edit

Wrap a Java bean in a COM object (using Sun ActiveX bridge) 168
Real's HowTo PDF version

the REG file to specify the original JRE\bin and update the registry with the good location.

The Bean is now registered and ready to be used as a COM object.

NOTE: There is a command-line interface available in the packager if you want to bypass the wizard.

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

' VBSCRIPT connect to a Java Bean


Dim objJava
Set objJava = WScript.CreateObject("JavaBeanSays.Bean")

strFromJava = objJava.getHello
MsgBox strFromJava, _
0, _
"JAVA BEAN OUTPUT"

objJava.setHello("Bonjour le monde!")

strFromJava = objJava.getHello
MsgBox strFromJava, _
0, _
"JAVA BEAN OUTPUT"

NOTE: Check the JAVA PLUG-IN SCRIPTING documentation (jdk1.2) or (jsdk1.4). document for more infos.

Query the Windows Registry (reg.exe)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0480.html

We launch the REG utility and capture the output. The performance is poor so it's a good idea to cache
frequently used values.

Note : The Microsoft Windows NT Server 4.0 Resource Kit contains REG.EXE. In Windows 2000 and later REG.EXE is a native command. The REG utility
can be used to write values in the registry (reg add /? for more infos).

In this example,we query the registry to extract the personal folder path ("My Documents") and the processor
ID and its name.

import java.io.*;

public class RegQuery {

private static final String REGQUERY_UTIL = "reg query ";


private static final String REGSTR_TOKEN = "REG_SZ";
private static final String REGDWORD_TOKEN = "REG_DWORD";

private static final String PERSONAL_FOLDER_CMD = REGQUERY_UTIL +

Query the Windows Registry (reg.exe) 169


Real's HowTo PDF version

"\"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\"
+ "Explorer\\Shell Folders\" /v Personal";
private static final String CPU_SPEED_CMD = REGQUERY_UTIL +
"\"HKLM\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\""
+ " /v ~MHz";
private static final String CPU_NAME_CMD = REGQUERY_UTIL +
"\"HKLM\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\""
+ " /v ProcessorNameString";

public static String getCurrentUserPersonalFolderPath() {


try {
Process process = Runtime.getRuntime().exec(PERSONAL_FOLDER_CMD);
StreamReader reader = new StreamReader(process.getInputStream());

reader.start();
process.waitFor();
reader.join();

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

Query the Windows Registry (reg.exe) 170


Real's HowTo PDF version

public static String getCPUName() {


try {
Process process = Runtime.getRuntime().exec(CPU_NAME_CMD);
StreamReader reader = new StreamReader(process.getInputStream());

reader.start();
process.waitFor();
reader.join();

String result = reader.getResult();


int p = result.indexOf(REGSTR_TOKEN);

if (p == -1)
return null;

return result.substring(p + REGSTR_TOKEN.length()).trim();


}
catch (Exception e) {
return null;
}
}

static class StreamReader extends Thread {


private InputStream is;
private StringWriter sw;

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

Query the Windows Registry (reg.exe) 171


Real's HowTo PDF version

See also this HowTo and this one.

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

Query/Update the Windows Registry (hack)


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

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

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

public class WinRegistry {


// inspired by
// http://javabyexample.wisdomplug.com/java-concepts/34-core-java/62-java-registry-wrapper.ht
// http://www.snipcode.org/java/1-java/23-java-class-for-accessing-reading-and-writing-from-w
// http://snipplr.com/view/6620/accessing-windows-registry-in-java/
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 static final int KEY_ALL_ACCESS = 0xf003f;


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

Query/Update the Windows Registry (hack) 172


Real's HowTo PDF version

private static Method regDeleteKey = null;


private static 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(
"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

Query/Update the Windows Registry (hack) 173


Real's HowTo PDF version

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

Query/Update the Windows Registry (hack) 174


Real's HowTo PDF version

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
* @param value
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public static void writeStringValue
(int hkey, String key, String valueName, String value)

Query/Update the Windows Registry (hack) 175


Real's HowTo PDF version

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

Query/Update the Windows Registry (hack) 176


Real's HowTo PDF version

}
else if (hkey == HKEY_CURRENT_USER) {
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

Query/Update the Windows Registry (hack) 177


Real's HowTo PDF version

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

Query/Update the Windows Registry (hack) 178


Real's HowTo PDF version

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[] {
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(

Query/Update the Windows Registry (hack) 179


Real's HowTo PDF version

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",
"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\Réal\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.

Query/Update the Windows Registry (hack) 180


Real's HowTo PDF version

Quickly retrieve available Java JVM on a workstation (Windows)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0525.html

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

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

Quickly retrieve available Java JVM on a workstation (Windows) 181


Real's HowTo PDF version

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 one-liner
displays the java.exe (if any) found in the PATH :

c:\> for %i in (java.exe) do @echo. %~$PATH:i


C:\WINDOWS\system32\java.exe

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.

Detect if a Windows service is running (capture VBS return


code)
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0575.html

You can't detect directly if Windows service is running or not in Java.

However, it's easy to do from a VBS. You execute the script from Java, wait for its completion and capture
the return code.

Obviously, this is useful only on the Windows plateform.

Detect if a Windows service is running (capture VBS return code) 182


Real's HowTo PDF version

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

public static void msgBox(String msg) {


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

Detect if a Windows service is running (capture VBS return code) 183


Real's HowTo PDF version

List currently running processes (Windows)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0593.html

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();
String result = "";

// display the result


Iterator<String> it = processes.iterator();
int i = 0;

List currently running processes (Windows) 184


Real's HowTo PDF version

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

Using a VBS

Another technique to build the required VBScript on-the-fly, execute it and capture its output.

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.util.*;

public class VBSUtils {


private VBSUtils() { }

public static List<String> listRunningProcesses() {


List<String> processList = new ArrayList<String>();
try {

File file = File.createTempFile("realhowto",".vbs");


file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);

String vbs = "Set WshShell = WScript.CreateObject(\"WScript.Shell\")\n"


+ "Set locator = CreateObject(\"WbemScripting.SWbemLocator\")\n"
+ "Set service = locator.ConnectServer()\n"
+ "Set processes = service.ExecQuery _\n"
+ " (\"select name from Win32_Process\")\n"
+ "For Each process in processes\n"
+ "wscript.echo process.Name \n"
+ "Next\n"
+ "Set WSHShell = Nothing\n";

fw.write(vbs);
fw.close();
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
BufferedReader input =

List currently running processes (Windows) 185


Real's HowTo PDF version

new BufferedReader
(new InputStreamReader(p.getInputStream()));
String line;
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.

Check if a program or process is running (Windows)


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

Check if a program or process is running (Windows) 186


Real's HowTo PDF version

import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;

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)

Check if a program or process is running (Windows) 187


Real's HowTo PDF version

null, msg, "VBSUtils", javax.swing.JOptionPane.DEFAULT_OPTION);


}
}

See also this HowTo

Check if a process is running (Windows) using WMIC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../gp/windows-detect-if-a-process-is-running.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 case-insensitive.

For Java code :

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import 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();

Check if a process is running (Windows) using WMIC 188


Real's HowTo PDF version

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

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


System.out.println(WindowsUtils2.isProcessRunning("excel.exe"));
}
}

See also this HowTo.

Windows registry vs Java JDK/JRE installation


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0604.html

The JDK itself does not use the windows registry to run.

It is the JRE that uses the system registry to run in some situations like an Applet or a program started with
the WebStart technolgy.

Finally, the JRE will only use the registry if it is run from the Windows system directory (ex .
C:/winnt/system32/java.exe). This would happen if the user just types "java" on the commandline in some
random directory, because the system directory is always in the user's path. In this situation, the java.exe will
locate the current Java installation by looking at the registry key

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\CurrentVersion]

and then get the path of the JRE from the corresponding key

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.5\JavaHome]

Beware that some software (eg. Oracle) installs themself at the beginning of the PATH definition, so it's their
Java installation that will be found first.

Windows registry vs Java JDK/JRE installation 189


Real's HowTo PDF version

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 WebStart-based programs, the registry is always used to determine the current
JRE.

Get the current Java version from a BAT file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0642.html

This command file queries the registry to find out the path of the current JRE installation and then launch it to
display the version found .

[j.cmd Win7 or better version]

@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=2 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=2 tokens=3*" %%A IN (`REG QUERY %JAVA_CURRENT% /v %JAVA_HOME% 2^>nul`) DO
set JAVA_PATH=%%A %%B
)
echo the path of the current Java JVM according to the registry is
echo %JAVA_PATH%

Get the current Java version from a BAT file 190


Real's HowTo PDF version

echo.
echo now if we try it :
"%JAVA_PATH%\bin\java.exe" -version
:end

[j.cmd XP version]

@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

Output :

>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

Get the current Java version from a BAT file 191


Real's HowTo PDF version

now if we try it :
java version "1.6.0_06"
Java(TM) SE Runtime Environment (build 1.6.0_06-b02)
Java HotSpot(TM) Client VM (build 10.0-b22, mixed mode, sharing)

To check a Java 32-bit installation on a 64-bit OS then change


HKLM\SOFTWARE\JavaSoft\Java Runtime Environment\...
for
HKLM\SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environment\...

Get the Windows "My Documents" path


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0572.html

This value is stored in the registry and there is no easy way to get it with regular Java unless you execute an
external utility, see this HowTo.

As an alternative, we can use a method provided by the JFileChooser class.

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)

Get the Windows Desktop path


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

Get the Windows "My Documents" path 192


Real's HowTo PDF version

+ "Explorer\\Shell Folders\" /v DESKTOP";

private WindowsUtils() {}

public static String getCurrentUserDesktopPath() {


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

Get the Windows Desktop path 193


Real's HowTo PDF version

String getResult() {
return sw.toString();
}
}
}

See also Get Windows Special Folders (JNA)

Get the Windows Special Folders


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0653.html

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

public class VBSUtils {

public static String SF_ALLUSERSDESKTOP = "AllUsersDesktop";


public static String SF_ALLUSERSSTARTMENU = "AllUsersStartMenu";
public static String SF_ALLUSERSPROGRAMS = "AllUsersPrograms";
public static String SF_ALLUSERSSTARTUP = "AllUsersStartup";
public static String SF_DESKTOP = "Desktop";
public static String SF_FAVORITES = "Favorites";
public static String SF_MYDOCUMENT = "MyDocuments";
public static String SF_PROGRAMS = "Programs";
public static String SF_RECENT = "Recent";
public static String SF_SENDTO = "SendTo";
public static String SF_STARTMENU = "StartMenu";
public static String SF_STARTUP = "Startup";

private VBSUtils() { }

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

Get the Windows Special Folders 194


Real's HowTo PDF version

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

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

See also Get Windows Special Folders (JNA)

Create an Internet Shortcut


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

Create an Internet Shortcut 195


Real's HowTo PDF version

* @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";
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");

Create an Internet Shortcut 196


Real's HowTo PDF version

}
}

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.

Detect if running in remote session (Windows)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-detect-remote-session.html

[Windows only]
To detect if an application is running in a Remote Desktop session, you can call the Windows API
GetSystemMetrics. The GetSystemMetrics() function will return a non-zero value with a
SM_REMOTESESSION parameter value if the application is associated with a client terminal session.

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 (nativecall-0,4,1.jar and nativeloader-200505172341.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 {

Detect if running in remote session (Windows) 197


Real's HowTo PDF version

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.

Detect if running in a Citrix session (Windows)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-detect-if-running-in-citrix-session.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");
}

Detect if running in a Citrix session (Windows) 198


Real's HowTo PDF version

Create a Taglet to document database access (Javadoc)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0473.html

Since JDK1.4, it is possible to create a taglet to be used with javadoc to customized the generated
documentation.

This example implements a new javadoc tag to document which tables a class is dealing with. If a method
interact with 2 tables, employee and address, then the javadoc tag

/**
*@table employee:firstname,lastname;address:city,country
* @return value
*/
public String newMethod() {
return "yo";
}

will be documented as

newMethod

public java.lang.String newMethod()

Returns:
value
Table(s):
employee address
firstname city
lastname country

The "table" taglet source

/*
* Table.java
*/

package com.rgagnon.taglet;
import com.sun.tools.doclets.Taglet;
import com.sun.javadoc.*;
import java.util.Map;
/**
* This is a taglet to document tables and fields used by a classes
* example : @table employee:lastname,firstname;address:city,country

Create a Taglet to document database access (Javadoc) 199


Real's HowTo PDF version

*
* @author Réal 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;
}

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

Create a Taglet to document database access (Javadoc) 200


Real's HowTo PDF version

*/
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) {
tagletMap.remove(tag.getName());
}
tagletMap.put(tag.getName(), tag);
}

/**
* Given the <code>Tag</code> representation of this custom
* tag, return its string representation.

Create a Taglet to document database access (Javadoc) 201


Real's HowTo PDF version

* @param tag the <code>Tag</code> representation of this custom tag.


*/
public String toString(Tag tag) {
String output = "";
String tables [] = tag.text().split(";");
int j = tables.length;
if (j > 0) {
output = "<DT><B>" + HEADER
+ "</B><DD><TABLE><TR>";
for (int i=0; i < j ; i++){
// deals with the current table and its fields
String current[] = tables[i].split(":");
output +=
"<TD><TABLE style=\"border-style:solid;"
+ " border-width:thin\">";
output +=
"<TH ALIGN=\"center\" STYLE=\"border-style:solid;"
+ " border-width:thin\">"
+ current[0] + "</TH>";
if (current.length > 1) {
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 :

Create a Taglet to document database access (Javadoc) 202


Real's HowTo PDF version

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.

Generate the Javadoc "en français"


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0437.html

The javadoc utility uses the regular Java mechanism to internationalize its output. The tools.jar in the lib
directory contains the resource bundle standard.properties used by Javadoc to generated the labels. To add a
new language, you need to create the appropriate resource bundle, in our case for french, we need a file called
standard_fr.properties.

The new file must be in the package com.sun.tools.doclets.standard.resources.

Extract from tools.jar, the standard.properties files (keep the directory structure). Copy it under the name
standard_fr.properties. Translate it (or you can download my "incomplete" version here).

[standard.properties (extract)]

doclet.Window_Split_Index={0}\: {1}-Index
doclet.Packages=Packages
doclet.SerialData=Serial Data\:
doclet.Since=Since\:
doclet.Warn_inline_taglet=Inline tag {0} should only be used with a {1}.
doclet.ClassUse_Subinterface=Subinterfaces of {0} in {1}
doclet.Frame_Version=Frame version
doclet.Generated_Docs_Untitled=Generated Documentation (Untitled)

[standard_fr.properties (extract)]

doclet.Window_Split_Index={0}\: {1}-Index
doclet.Packages=Paquetages
doclet.SerialData=Donn\u00E9e s\u00E9rialis\u00E9e\:
doclet.Since=Depuis\:
doclet.Warn_inline_taglet=Inline tag {0} should only be used with a {1}.
doclet.ClassUse_Subinterface=Sous-interfaces de {0} dans {1}

Generate the Javadoc "en français" 203


Real's HowTo PDF version

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>

Document a package using Javadoc


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0502.html

Suppose I have a package called com.rgagnon with one HelloWorld class.

com
rgagnon
HelloWorld.java

In the directory containing HelloWorld.java, add a file called package.html.

This must be a complete HTML file (with HEAD and BODY). the first line of the body will be used a the
package description by javadoc.

<html><head></head><body>
this is <i>com.rgagnon</i> package description,
see <a href="http://www.rgagnon.com" target="_top">web site</a>
</body></html>

Document a package using Javadoc 204


Real's HowTo PDF version

Now execute the javadoc utility located in [JDK]\bin directory from the root of the com.rgagnon package.

\progra~1\Java\jdk1.5.0\bin\javadoc -d javadoc0 -linksource com.rgagnon

where -d javadoc0 is used to specify the output directory and


-linksource to create HTML version of the source file.

See the result.

Since JDK 1.5, to create a package comment file, you have a choice of two files to place your comments:

• package-info.java - Can contain a package declaration, package annotations, package comments and
Javadoc tags. This file is new in JDK 5.0, and is preferred over package.html.
• package.html - Can contain only package comments and Javadoc tags, no package annotations.

See http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/javadoc.html#packagecomment

Display a comment in a Javadoc


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

Display a comment in a Javadoc 205


Real's HowTo PDF version

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

Display XML in a Javadoc


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

Display XML in a Javadoc 206


Real's HowTo PDF version

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

Add a copyright notice to a Javadoc


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0626.html

Use the -bottom parameter to the javadoc command line.

-bottom '<font size="-1"><a href="http://www.rgagnon.com">Real&apos;s HowTo</a>


<br>&copy; 2008 rgagnon.com</font>'

The result looks like this :

Use a Log file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0501.html

Since 1.4, a logging functionnality is included with the JDK. It's the java.util.logging package.

Add a copyright notice to a Javadoc 207


Real's HowTo PDF version

import java.util.logging.*;
import java.io.*;

public class TestLog {

public static Logger logger;

static {
try {
boolean append = true;
FileHandler fh = new FileHandler("TestLog.log", append);
//fh.setFormatter(new XMLFormatter());
fh.setFormatter(new SimpleFormatter());
logger = Logger.getLogger("TestLog");
logger.addHandler(fh);
}
catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String args[]) {


logger.severe("my severe message");
logger.warning("my warning message");
logger.info("my info message");
}
}

and the result is

2005-02-28 21:19:28 TestLog main


GRAVE: my severe message
2005-02-28 21:19:28 TestLog main
ATTENTION: my warning message
2005-02-28 21:19:28 TestLog main
INFO: my info message

if the XMLFormatter is in use then the output is

<?xml version="1.0" encoding="windows-1252" standalone="no"?>


<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
<date>2005-02-28T21:21:09</date>
<millis>1109643669250</millis>
<sequence>0</sequence>
<logger>TestLog</logger>
<level>SEVERE</level>
<class>TestLog</class>
<method>main</method>
<thread>10</thread>
<message>my severe message</message>
</record>

Use a Log file 208


Real's HowTo PDF version

<record>
<date>2005-02-28T21:21:09</date>
<millis>1109643669328</millis>
<sequence>1</sequence>
<logger>TestLog</logger>
<level>WARNING</level>
<class>TestLog</class>
<method>main</method>
<thread>10</thread>
<message>my warning message</message>
</record>
<record>
<date>2005-02-28T21:21:09</date>
<millis>1109643669328</millis>
<sequence>2</sequence>
<logger>TestLog</logger>
<level>INFO</level>
<class>TestLog</class>
<method>main</method>
<thread>10</thread>
<message>my info message</message>
</record>
</log>

to customize the output, you can provide you own formatter

import java.util.logging.*;
import java.io.*;

public class TestLog {

public static Logger logger;

static {
try {
boolean append = true;
FileHandler fh = new FileHandler("TestLog.log", append);
fh.setFormatter(new Formatter() {
public String format(LogRecord rec) {
StringBuffer buf = new StringBuffer(1000);
buf.append(new java.util.Date());
buf.append(' ');
buf.append(rec.getLevel());
buf.append(' ');
buf.append(formatMessage(rec));
buf.append('\n');
return buf.toString();
}
});
logger = Logger.getLogger("TestLog");
logger.addHandler(fh);
}
catch (IOException e) {
e.printStackTrace();

Use a Log file 209


Real's HowTo PDF version

}
}

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

Trace the execution


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0301.html

Trace the execution 210


Real's HowTo PDF version

JDK1.5+

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)

Trace the execution 211


Real's HowTo PDF version

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

See also this Howto


• Get the current or calling method name.

Time the execution


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0132.html

public class ExecutionTimer {


private long start;
private long end;

public ExecutionTimer() {
reset();
}

public void start() {


start = System.currentTimeMillis();
}

public void end() {


end = System.currentTimeMillis();
}

public long duration(){


return (end-start);
}

public void reset() {


start = 0;
end = 0;
}

public static void main(String s[]) {


// simple example
ExecutionTimer t = new ExecutionTimer();
t.start();
for (int i=0; i < 80; i++){ System.out.print(".");}
t.end();
System.out.println("\n" + t.duration() + " ms");
}
}

Time the execution 212


Real's HowTo PDF version

See this HowTo to format a duration in ms into a string as "Days , Hours , minutes and seconds".

Log information efficiently (with Log4J)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0527.html

In production code, a good practice is to only log what is necessary in the context.

With Log4J, you can have different levels of message written into your log.

public class MyClass {

/**
* Logger log4j
*/
static Logger logger = Logger.getLogger(MyClass.class.getName());

...
logger.debug("I'm here");
logger.info(e.getMessage());
logger.warning("something wrong " + e.getMessage());
logger.error("omg " + e.getMessage());
...

While you can set the level in your code with something like

logger.setLevel(Level.WARN);

it's more flexible to do it from the Log4J properties file

; can be OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL


log4j.threshold=WARN

You put the properties file in the classpath and then from your code

URL url = ClassLoader.getSystemResource("log4j.props");


PropertyConfigurator.configure(url);

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.

Log information efficiently (with Log4J) 213


Real's HowTo PDF version

The best practice is to check if the level is enabled or not.

logger.setLevel(Level.DEBUG);
if (logger.isDebugEnabled()) {
logger.debug("something wrong with the value of " + myValue.toString());
}

This way you will not incur the cost of parameter construction if debugging is disabled for logger.

You can even remove the unwanted logging operation from the bytecode! See this HowTo.

Finally it's a good idea to design a robust toString() method for your class like this one :

public String toString(){


StringBuffer sb = new StringBuffer();
sb.append(getClass().getName())
sb.append(" myValue=[").append(this.myValue).append("]");
sb.append(" anotherValue=[").append(this.anotherProperty).append("]");
return sb.toString();
}

even if myValue is null, this toString() method will display "null" as the value and not throw a
NullPointerExeception.

See also this HowTo and this one

Change the logging level on-the-fly (Log4J)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0621.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 on-the-fly 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)) {

Change the logging level on-the-fly (Log4J) 214


Real's HowTo PDF version

root.setLevel(org.apache.log4j.Level.DEBUG);
}
else {
root.setLevel(org.apache.log4j.Level.INFO);
}
}

Enable debug log level on OpenSource package(Apache


Commons Logging)
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-enable-debug-logging.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 bu
[DEBUG] ProjectResourceBundle - -Created org.apache.axis.i18n.resource, linked to parent null
[DEBUG] ProjectResourceBundle - -getBundle(org.apache.axis,org.apache.axis.utils,resource,nul
[DEBUG] ProjectResourceBundle - -loadBundle: Ignoring MissingResourceException: Can't find bu
[DEBUG] ProjectResourceBundle - -org.apache.axis.i18n.resource::handleGetObject(setMsgForm)
[DEBUG] SOAPPart - -Setting current message form to: FORM_STRING (currentMessage is now <?xml
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http:/
<soapenv:Header>
<ns1:biBusHeader soapenv:mustUnderstand="0" xmlns:ns1="http://developer.cognos.com/schemas/
</soapenv:Header>
<soapenv:Body>
<ns2:logon soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="htt

...

[DEBUG] HTTPSender - -HTTP/1.1 405 Method Not Allowed


[DEBUG] HTTPSender - -Allow OPTIONS, TRACE, GET, HEAD
[DEBUG] HTTPSender - -Content-Length 1564
[DEBUG] HTTPSender - -Content-Type text/html
[DEBUG] HTTPSender - -Server Microsoft-IIS/6.0

...

Enable debug log level on OpenSource package(Apache Commons Logging) 215


Real's HowTo PDF version

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 - >> "User-Agent: Axis2[\r][\n]"
2009/08/21 12:15:56:109 EDT [DEBUG] header - >> "Host: api.sandbox.ebay.com[\r][\n]"
2009/08/21 12:15:56:109 EDT [DEBUG] header - >> "Content-Length: 1546[\r][\n]"
2009/08/21 12:15:56:109 EDT [DEBUG] header - >> "Content-Type: text/xml; charset=UTF-8[\r][\n
2009/08/21 12:15:56:109 EDT [DEBUG] header - >> "[\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);
}

Make a JAR executable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0166.html

In the manifest file of a JAR, it is possible to specify the class to be used when the JVM is lauched with the
JAR as parameter. The class must have a main().

Try with this simple class

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

public class MyClass {


public static void main(String[] args) {
Frame f = new Frame();
f.addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);

Make a JAR executable 216


Real's HowTo PDF version

f.add(new Label("Hello world"));


f.setSize(200,200);
f.setVisible(true);
}
}

Then create this manifest file (manifest.mft) with any text editor.

Manifest-Version: 1.0
Main-Class: MyClass
Class-path: .

Main-Class specifies the entry point with the main(String args[]) method.

The Class-path is used to specify the dependency of this jar (if any). You add the directories and jars
separated by a space. It is important because when running a jar , the CLASSPATH definition (as defined
by the environnement variable) is overridden.

Next, you include the manifest file in the JAR (MyJar.jar) with the MyClass class.

jar cvfm myjar.jar manifest.mft *.class

Then you are able to start the MyClass.class by double-clicking on the MyJar.jar file (if the JRE is correctly
installed) or by typing

java -jar myjar.jar

If you need to pass parameters, use the -D switch before the -jar switch and use the getProperty() method to
get the value.

The file association mechanism is made during the installation of the JRE.

You can verify that everything is ok with the following command from a DOS Shell

>assoc .jar
.jar=jarfile

>ftype jarfile
jarfile="C:\Program Files\Java\jre1.5.0_10\bin\javaw.exe" -jar "%1" %*

If the association is broken or you need to change the JRE used then by using the assoc/ftype utilities, you
can modify the association easily (use /? to display the syntax of the assoc and ftype utilities).

NOTE: On WinXp (or better), your user account needs to be at the Admin level.

On Windows (NT or better), you can also make JARs run from the command-line by setting the PATHEXT
environment variable, for example
SET PATHEXT=.EXE;.BAT;.CMD;.JAR

Make a JAR executable 217


Real's HowTo PDF version

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

Application with multiples Jars


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0319.html

Supposed we have a jar called Main.jar for the application. This application needs Second.jar and Third.jar
. In the manifest file of the first jar (Main.jar), you adjust the Class-Path setting :

Manifest-Version: 1.0
Main-Class: MyClass
Class-Path: Second.jar Third.jar

The value of the Class-Path attribute specifies the relative URLs of the extensions or libraries that this
application or extension needs. URLs are separated by one or more spaces. The application or extension
class loader uses the value of this attribute to construct its internal search path.

You can use the -i option to speed up your application's class loading time:
jar -i main.jar

This will build an an INDEX.LIST file in the META-INF directory which will enable the application class
loader to download the right jar files when it is searching for classes or resources.

Extract a file from a Jar


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0429.html

The following snippet extract a file (mydb.mdb) from a jar.

import java.io.*;
import java.util.jar.*;
import java.util.zip.*;

public class ExtractFromJAR {

public void extractMyMDBromJAR(String dest){


try {
String home = getClass().getProtectionDomain().
getCodeSource().getLocation().toString().
substring(6);

Application with multiples Jars 218


Real's HowTo PDF version

JarFile jar = new JarFile(home);


ZipEntry entry = jar.getEntry("mydb.mdb");
File efile = new File(dest, entry.getName());

InputStream in =
new BufferedInputStream(jar.getInputStream(entry));
OutputStream out =
new BufferedOutputStream(new FileOutputStream(efile));
byte[] buffer = new byte[2048];
for (;;) {
int nBytes = in.read(buffer);
if (nBytes <= 0) break;
out.write(buffer, 0, nBytes);
}
out.flush();
out.close();
in.close();
}
catch (Exception e) {
e.printStackTrace();
}
}

public static void main(String args []){


new ExtractFromJAR().extractMyMDBFromJAR(".");
}

Grab this auto-run Jar if you want to try it.

To create an auto-run JAR, first create a manifest.mft

Manifest-Version: 1.0
Classpath: .\mydb.jar
Main-Class: ExtractFromJAR

Create the JAR

C:\jdk141\bin\jar cvfm mydb.jar manifest.mft ExtractFromJAR.class mydb.mdb

Run it ... and the mydb.mdb file should appear in the current directory.

java -jar mydb.jar

(A tip from Fred Hommersom) Your code reads:


String home = getClass().getProtectionDomain().
getCodeSource().getLocation().toString().substring(6);

Extract a file from a Jar 219


Real's HowTo PDF version

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

Determine if running from JAR


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0391.html

package com.rgagnon;

public class HelloClass {


public static void main(String[] args) {
new HelloClass().say();
}

public void say() {


String className = this.getClass().getName().replace('.', '/');
String classJar =
this.getClass().getResource("/" + className + ".class").toString();
if (classJar.startsWith("jar:")) {
System.out.println("*** running from jar!");
}
System.out.println(classJar);
}
}

The output

>jar cvfm Hello.jar manifest.mft com\rgagnon\HelloClass.class


added manifest
adding: com/rgagnon/HelloClass.class (in=1059) (out=601) (deflated 43%)

>java com.rgagnon.HelloClass
file:/C:/DEV/WORK/JAVA/com/rgagnon/HelloClass.class

>java -jar Hello.jar


*** running from jar!
jar:file:/C:/DEV/WORK/JAVA/Hello.jar!/com/rgagnon/HelloClass.class

Here a variation on this subject, a method to return the name of the current running jar.

package com.rgagnon.howto;

public class RunningJar {

Determine if running from JAR 220


Real's HowTo PDF version

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

>java -jar yip.jar


Running from yip.jar

*/

See these related HowTo's : Obtain from where a Class is loaded Get the "root" of an application

Get list of classes in package (in a Jar)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0513.html

import java.util.jar.*;
import java.util.*;
import java.io.*;

Get list of classes in package (in a Jar) 221


Real's HowTo PDF version

public class PackageUtils {

private static boolean debug = true;

private PackageUtils() {}

public static List getClasseNamesInPackage


(String jarName, String packageName){
ArrayList classes = new ArrayList ();

packageName = packageName.replaceAll("\\." , "/");


if (debug) System.out.println
("Jar " + jarName + " looking for " + packageName);
try{
JarInputStream jarFile = new JarInputStream
(new FileInputStream (jarName));
JarEntry jarEntry;

while(true) {
jarEntry=jarFile.getNextJarEntry ();
if(jarEntry == null){
break;
}
if((jarEntry.getName ().startsWith (packageName)) &&

(jarEntry.getName ().endsWith (".class")) ) {


if (debug) System.out.println
("Found " + jarEntry.getName().replaceAll("/", "\\."));
classes.add (jarEntry.getName().replaceAll("/", "\\."));
}
}
}
catch( Exception e){
e.printStackTrace ();
}
return classes;
}

/**
*
*/
public static void main (String[] args){
List list = PackageUtils.getClasseNamesInPackage
("C:/j2sdk1.4.1_02/lib/mail.jar", "com.sun.mail.handlers");
System.out.println(list);
/*
output :

Jar C:/j2sdk1.4.1_02/lib/mail.jar looking for com/sun/mail/handlers


Found com.sun.mail.handlers.text_html.class
Found com.sun.mail.handlers.text_plain.class
Found com.sun.mail.handlers.text_xml.class
Found com.sun.mail.handlers.image_gif.class

Get list of classes in package (in a Jar) 222


Real's HowTo PDF version

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]

*/
}
}

Add version to Jar packaging


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0388.html

Let's say we have the following class (package is mandatory)

package com.rgagnon;

public class Hello {


public static void main(String[] args) {
new Hello().say("Hello World!");
}

public void say(String s) {


System.out.println(s);
}
}

First create a MANIFEST.MF file :

Manifest-Version: 1.0
Main-Class: com.rgagnon.Hello

Then build the executable Jar and run it.

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

>java -jar hello.jar


Hello World!

Now modify the manifest to include versioning information.

Manifest-Version: 1.0
Main-Class: com.rgagnon.Hello
Specification-Version: 2.1
Implementation-Version: 1.1

Add version to Jar packaging 223


Real's HowTo PDF version

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 {

private JarUtils() {}

public static String getJarImplementationVersion(String jar)


throws java.io.IOException
{
JarFile jarfile = new JarFile(jar);
Manifest manifest = jarfile.getManifest();
Attributes att = manifest.getMainAttributes();
return att.getValue("Implementation-Version");
}

Add version to Jar packaging 224


Real's HowTo PDF version

public static String getJarSpecificationVersion(String jar)


throws java.io.IOException
{
JarFile jarfile = new JarFile(jar);
Manifest manifest = jarfile.getManifest();
Attributes att = manifest.getMainAttributes();
return att.getValue("Specification-Version");
}
public static void main(String[] args) throws java.io.IOException{
String javaMailJar = "C:/Program Files/Java/jre1.5.0/lib/mail.jar";

System.out.println("Specification-Version: "
+ JarUtils.getJarSpecificationVersion(javaMailJar));
System.out.println("Implementation-Version: "
+ JarUtils.getJarImplementationVersion(javaMailJar));
/*
* output :
* Specification-Version: 1.3
* Implementation-Version: 1.3.1
*/
}
}

Use ANT to Build a JAR with version/build number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0532.html

• Download ANT from http://ant.apache.org/bindownload.cgi


• Unzip into the root of C: (Windows), rename the folder to \Ant
• Create a file call antenv.cmd. Before using ANT, you must execute this file to set up the environment. You
may need to adjust the values according to your installation!
set ANT_HOME=c:\ant
set JAVA_HOME=C:\Progra~1\Java\jdk1.5.0
set PATH=%ANT_HOME%\bin;%JAVA_HOME%\bin;%path%
• Create a simple Hello class as shown below (you need have a package).
package howto;
public class Hello {
public static void main( String[] args ){
System.out.println( "Hello World" );
}
}
• Execute your antenv.cmd to set the environment
• Compile your Hello class and make a jar to check if your environment is ok.
> javac howto/Hello.java
> jar -cvf hello.jar howto/Hello.class
added manifest
adding: howto/hello.class(in = 415) (out= 284) (deflated 31%)
> java -cp hello.jar howto.Hello
Hello World

Use ANT to Build a JAR with version/build number 225


Real's HowTo PDF version

• Create a build.xml which is the default ant build file ...


• ... and load it into your favorite editor. Type the following ant script and save it.
<project default="buildHello">
<target name="compile">
<javac srcdir="." />
</target>

<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 EST 2006 META-INF/
55 Wed May 03 17:06:32 EST 2006 META-INF/MANIFEST.MF
55 Wed May 03 17:06:32 EST 2006 howto/
335 Wed May 03 16:36:16 EST 2006 howto/Hello.class
• Try your new Jar file
> java -cp Hello.jar howto.Hello
Hello World

Use ANT to Build a JAR with version/build number 226


Real's HowTo PDF version

• Make your Jar auto-executable by specifying the Main class into a MANIFEST.MF file to be included in
the Jar. Add the following lines to build.xml
<project default="buildHello">
<target name="compile">
<javac srcdir="." />
</target>

<target name="jar" depends="compile">


<delete file="hello.jar"/>
<delete file="MANIFEST.MF"/>
<manifest file="MANIFEST.MF">
<attribute name="Built-By" value="${user.name}"/>
<attribute name="Main-Class" value="howto.Hello"/>
</manifest>

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

<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 hard-coded in the script but you can read it from a
file.
<project default="buildHello">
<target name="compile">
<javac srcdir="." />
</target>

<target name="jar" depends="compile">


<delete file="hello.jar"/>
<delete file="MANIFEST.MF"/>
<property name="version.num" value="1.00"/>
<buildnumber file="build.num"/>

<manifest file="MANIFEST.MF">
<attribute name="Built-By" value="${user.name}"/>
<attribute name="Main-Class" value="howto.Hello"/>
<attribute name="Implementation-Version"
value="${version.num}-b${build.number}"/>
</manifest>

<jar destfile="hello.jar"
basedir="."

Use ANT to Build a JAR with version/build number 227


Real's HowTo PDF version

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
Implementation-Version: 1.00-b1
• and after the next build operation, the entry will be
Implementation-Version: 1.00-b2
• Modify the Hello class to read the Implementation-Version information and display it.
package howto;

public class Hello {


public static void main( String[] args ){
System.out.println( "Hello World ");
System.out.println("version : " +
Hello.class.getPackage().getImplementationVersion() );
}
}
• Finally we add a target to cleanup and the main target to build everything to the build.xml file.
<project default="buildHello">
<target name="compile">
<javac srcdir="." />
</target>

<target name="jar">
<delete file="hello.jar"/>
<property name="version.num" value="1.00"/>
<buildnumber file="build.num"/>

<manifest file="MANIFEST.MF">
<attribute name="Built-By" value="${user.name}"/>
<attribute name="Main-Class" value="howto.Hello"/>
<attribute name="Implementation-Version"
value="${version.num}-b${build.number}"/>
</manifest>

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

<target name="cleanup">
<delete>
<fileset dir="." includes="**/*.class"/>
<fileset file="MANIFEST.MF"/>
</delete>
</target>

<target name="buildHello" depends="compile,jar,cleanup" />

Use ANT to Build a JAR with version/build number 228


Real's HowTo PDF version

</project>
• Build and launch the Hello class
> ant buildHello
...
> java -jar hello.jar
Hello World
version : 1.00-b3

b3 == build #3 (if it's your third build !)

Build number is great but a Built date is useful too!

...
<target name="jar">
<delete file="hello.jar"/>
<property name="version.num" value="1.00"/>
<buildnumber file="build.num"/>
<tstamp>
<format property="TODAY" pattern="yyyy-MM-dd HH:mm:ss" />
</tstamp>

<manifest file="MANIFEST.MF">
<attribute name="Built-By" value="${user.name}"/>
<attribute name="Main-Class" value="howto.Hello"/>
<attribute name="Implementation-Version"
value="${version.num}-b${build.number}"/>
<attribute name="Built-Date" value="${TODAY}"/>
</manifest>

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

See also this Howto.

Include all jars in the classpath definition


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0587.html

Specifying all the required jar in the classpath can be a pain. Here some techniques to set the classpath
definition automatically.

Include all jars in the classpath definition 229


Real's HowTo PDF version

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

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

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

Include all jars in the classpath definition 230


Real's HowTo PDF version

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

JAR (and ANT)

The best solution when you have a jar is to try to include the required jars into the manifest declaration.

Manifest-Version: 1.0
Class-Path:
customer_client.jar
mailer_client.jar
signon_client.jar

The manifest file format restrictions mandated by the JDK requires the use of a space ' ' character as the line
continuation character, so ensure that your editor is not set up to trim trailing spaces on saves and exits.

The line with the Class-Path: header must end with a space character and each of the lines referencing the
client jar's should start and end with a space ' ' character and the manifest file as a whole must end with a
blank line.

Remember that when you launch an application with


java -jar myjar.jar

the CLASSPATH definition (as defined by the environment variable) is overriden by the "class-path"
defined the jar's manifest.

See http://java.sun.com/docs/books/tutorial/deployment/jar/downman.html

Ant can be used to build your Jar and built the manifest class-path definition.

<target name="MyJar" depends="dist, compile" description="generate jar" >


<jar destfile="${dist}/${jar}">
<manifest>
<attribute name="Main-Class" value="${Main_Class}"/>
<attribute name="Class-Path" value=". lib/utils.jar lib/client.jar" />
</manifest>
</jar>

Include all jars in the classpath definition 231


Real's HowTo PDF version

</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="Main-Class" value="com.mycompany.TestMain"/>
<attribute name="Class-Path" value="${manifest.classpath}"/>
</manifest>
</jar>
</target>

Latest Ant version (1.7) includes a task called ManifestClassPath which converts a classpath into a
space-separated list of items used to set the Manifest Class-Path attribute. See
http://ant.apache.org/manual/CoreTasks/manifestclasspath.html

<path id="build-classpath">
<fileset dir="${build.dir}">
<include name="*.jar"/>
</fileset>
</path>

<manifestclasspath property="lib.list" jarfile="${build.dir}/${jar.file}">


<classpath refid="build-classpath" />
</manifestclasspath>

<jar>
...
<manifest>
<attribute name="Main-Class" value="com.mycompany.TestMain"/>
<attribute name="Class-Path" value=". ${lib.list}"/>
</manifest>
...
</jar>

Include all jars in the classpath definition 232


Real's HowTo PDF version

Detect browser type from an Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-detect-browser-type-from-an-applet.html

Call a Javascript from the Applet

With LiveConnect, we call a javascript to return the "User-Agent".

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

Detect browser type from an Applet 233


Real's HowTo PDF version

<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/user-agent-utils/ or at this code : http://nerds.palmdrive.net/useragent/code.html
to get the idea.

Get the value from the server-side

When serving the HTML containing the Applet, you add the User-Agent as parameter for the Applet.

In a JSP/EL

<applet ... >


<param ... >
<param name="userAgent" value="${header['user-agent']}" />
</applet>

and in the Applet

String userAgent = getParameter("userAgent");

and parse the returned value...

Detect if Java is enabled from HTML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0161.html

For a Javascript solution, check this How-to

<HTML><HEAD></HEAD><BODY>
<APPLET CODE="MyApplet.class"
NAME="myApplet"
HEIGHT=400 WIDTH=400 ALT="Oups! You don't have JAVA enabled">
<A HREF="nojava.html">Oups! You don't have JAVA enabled, click here.</A>
</APPLET>

Detect browser type from an Applet 234


Real's HowTo PDF version

</BODY></HTML>

See the Java Console Window Log (Java plugin)


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

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

C:\Documents and Settings\


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

It's a file with the extension .trace

Written and compiled Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Detect if Java is enabled from HTML 235


Internationalization
java-inter

Load resources based upon client environment at startup


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0133.html

There are two ways to include resources based on the current Locale. One way is to use Properties files and
the other are classes extending the ListResourceBundle base class. You need to follow a naming standard so
that the JVM retrieves the right resources bundle.

Note that if a resource is missing for the current locale then the default definition is used.

[International.java (main program)]

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.text.*;

public class International extends JFrame


implements ActionListener
{
JLabel aLabel;
JLabel vLabel;
JCheckBox aCheckbox;
JButton aButton;
JButton vButton;
JTextField aTextField;
NumberFormat nf;

public void initGUI(){


setLayout(new FlowLayout());

// String
aLabel = new JLabel
(MyResources.rb.getString("aLabel"));
add(aLabel);

// Object
aCheckbox =
(JCheckBox)MyResources.rb.getObject("aCheckbox");
add(aCheckbox);

// String concatenation with MessageFormat

Internationalization 236
Real's HowTo PDF version

Date d = new Date();


MessageFormat mf = new MessageFormat
(MyResources.rb.getString("aButton"));
aButton = new JButton
(mf.format(new Object [] { d }));
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);
}
};

Load resources based upon client environment at startup 237


Real's HowTo PDF version

SwingUtilities.invokeLater(t);
}
}

[MyResources.java (default resources)]

import java.util.*;
import javax.swing.*;
import java.text.*;

public class MyResources extends ListResourceBundle {


public static ResourceBundle rb =
ResourceBundle.getBundle("MyResources");

public Object [][] getContents() {


return contents;
}

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;

Load resources based upon client environment at startup 238


Real's HowTo PDF version

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

This example uses ListResourceBundle classes to store the required resources. It is possible to substitute them
for Properties files without any change to the code. The properties files must have the .properties extension.

See this How-to.

Load resources dynamically


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0134.html

This HowTo lets you select a language and change its GUI to reflect the choice.

We are using a special class, a ListResourceBundle, to store our resources. We have a class per Locale. If a
specific resource is not in a specific Locale ListResourceBundle then the default resource is used.

To use a properties file instead of a class to store resources then look at this HowTo.

[InternationalDynamic.java (main program)]

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

Load resources dynamically 239


Real's HowTo PDF version

import javax.swing.*;

public class InternationalDynamic extends JFrame


implements ActionListener
{

static Locale[] localesSupported = {


Locale.US, Locale.FRANCE, Locale.GERMANY
};

int localeChoosen = 0;
Locale localeCurrent;
ResourceBundle rb;

ButtonGroup bg;
JButton btnQuit;
JRadioButton r0, r1, r2;
JLabel today;
boolean defaultDone = false;

public void initLocale(){


localeCurrent = localesSupported[localeChoosen];
this.setLocale(localeCurrent);
rb = ResourceBundle.getBundle("ResourcesDynamic", localeCurrent);
}

public void initText() {


setTitle (rb.getString("title"));
r0.setText(rb.getString("r0"));
r1.setText(rb.getString("r1"));
r2.setText(rb.getString("r2"));
btnQuit.setText(rb.getString("btnQuit"));
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

Load resources dynamically 240


Real's HowTo PDF version

if (!defaultDone) {
String rDef = rb.getString("rDefault");
if (rDef.equals("r0"))
r0.setSelected(true);
else if (rDef.equals("r1"))
r1.setSelected(true);
else
r2.setSelected(true);
defaultDone = true;
}
else {
if (localeChoosen == 0)
r0.setSelected(true);
else if (localeChoosen == 1)
r1.setSelected(true);
else
r2.setSelected(true);
}

// QUIT button
btnQuit = new JButton();
add(btnQuit);

// today label
today = new JLabel();
add(today);

//
r0.addActionListener(this);
r1.addActionListener(this);
r2.addActionListener(this);
btnQuit.addActionListener(this);

setSize(400,100);
setVisible(true);
}

public void actionPerformed(ActionEvent ae){


if (ae.getSource() == btnQuit) {
System.exit(0);
}
else if (ae.getSource() == r0) localeChoosen = 0;
else if (ae.getSource() == r1) localeChoosen = 1;
else if (ae.getSource() == r2) localeChoosen = 2;
initLocale();
initText();
pack();
}

public static void main(String args[]) {


System.out.println("Current Locale : " + Locale.getDefault());
Thread t = new Thread () {
public void run() {
InternationalDynamic i = new InternationalDynamic();

Load resources dynamically 241


Real's HowTo PDF version

i.initLocale();
i.initGUI();
i.initText();
i.pack();
}
};
SwingUtilities.invokeLater(t);
}
}

[ResourcesDynamic.java (default resources)]

import java.util.*;

public class ResourcesDynamic extends ListResourceBundle {


public Object [][] getContents() {
return contents;
}

static final Object[][] contents = {


{ "title", "Example" },
{ "r0" , "United States" } ,
{ "r1", "France" } ,
{ "r2" , "Germany"},
{ "rDefault" , "r0" },
{ "btnQuit" , "Quit"},
{ "today" , " (def) {0,date,long}"},
};
}

[ResourcesDynamic_en.java (english language resources)]

import java.util.*;

public class ResourcesDynamic_en extends ListResourceBundle {


public Object [][] getContents() {
return contents;
}

static final Object[][] contents = {


{ "title", "Example" },
{ "r0" , "United States" } ,
{ "r1", "France" } ,
{ "r2" , "Germany"},
{ "rDefault" , "r0" },
{ "btnQuit" , "Quit"},
{ "today" , " (en) {0,date,long}"},
};
}

[ResourcesDynamic_fr.java (french language resources)]

import java.util.*;

Load resources dynamically 242


Real's HowTo PDF version

public class ResourcesDynamic_fr extends ListResourceBundle {


public Object [][] getContents() {
return contents;
}

static final Object[][] contents = {


{ "title", "Exemple" },
{ "r0" , "Etats-Unis" } ,
{ "r1", "France" } ,
{ "r2", "Allemagne" },
{ "rDefault", "r1" },
{ "btnQuit", "Quitter" },
{ "today" , " (fr) {0,date, dd/MM/yyyy}"},
};
}

[ResourcesDynamic_de.java (german language resources)]

import java.util.*;

public class ResourcesDynamic_de extends ListResourceBundle {


public Object [][] getContents() {
return contents;
}
static final Object[][] contents = {
{ "title", "Beispiel" },
{ "r0" , "Vereinigte Staaten" } ,
{ "r1", "Frankreich" } ,
{ "r2", "Deutschland" },
{ "rDefault", "r2" },
{ "btnQuit", "verlassen"},
{ "today" , " (de) {0,date,dd.MM.yyyy}"},
};
}

Load resources via a resource file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0135.html

With the previous JAVA How-to, the resources were stored in classes. The drawback is when there is a
modification, we must recompile the class. With a resources file, we simply add or modify the resource in a
special file with a regular text editor. The JDK provides a class, PropertyResourceBundle, to use properties
file very easily. In fact, from the programmer's point of view, there is no difference if the resources are stored
in classes or properties files.

The ResourceBundle will look first for classes and if not found, it will look for properties files. We don't have
to specify filenames, the ResourceBundle will construct the filename using the same mechanism used for

Load resources via a resource file 243


Real's HowTo PDF version

classes. The file must have the extension .properties.

The ResourceBundle try to load the properties file from the current classpath.

If the properties are stored in subdirectory , use "." instead of "/".

For example, let's say that the properties file is in a subdirectory called "subdir" (from the current directory).
Then you can load the ResourcesDynamic resources file with

ResourceBundle.getBundle("subdir.ResourcesDynamic", localeCurrent);

[InternationalDynamic.java]

import java.util.*;
import java.text.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class InternationalDynamic extends JFrame


implements ActionListener
{

static Locale[] localesSupported = {


Locale.US, Locale.FRANCE, Locale.GERMANY
};

int localeChoosen = 0;
Locale localeCurrent;
ResourceBundle rb;

ButtonGroup bg;
JButton btnQuit;
JRadioButton r0, r1, r2;
JLabel today;
boolean defaultDone = false;

public void initLocale(){


localeCurrent = localesSupported[localeChoosen];
this.setLocale(localeCurrent);
rb = ResourceBundle.getBundle("res.ResourcesDynamic", localeCurrent);
}

public void initText() {


setTitle (rb.getString("title"));
r0.setText(rb.getString("r0"));
r1.setText(rb.getString("r1"));
r2.setText(rb.getString("r2"));
btnQuit.setText(rb.getString("btnQuit"));
Date d = new Date();
MessageFormat mf = new MessageFormat

Load resources via a resource file 244


Real's HowTo PDF version

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

Load resources via a resource file 245


Real's HowTo PDF version

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

[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]

Load resources via a resource file 246


Real's HowTo PDF version

title=Exemple
r0=Etats-Unis
r1=France
r2=Allemagne
rDefault=r1
btnQuit=Quitte
today=(fr) {0,date, dd/MM/yyyy}

[ResourcesDynamic_de.properties]

title=Beispiel
r0=Vereinigte Staaten
r1=Frankreich
r2=Deutschland
rDefault=r2
btnQuit=Verlassen
today=(de) {0,date,dd.MM.yyyy}

Display "special character" using Unicode


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0136.html

The copyright symbol © :

String COPYRIGHT = "\u00a9";

The registered symbol ® :

String REGISTERED = "\u00ae";

The euro-currency sign € :

String EURO = "\u20ac"

For example :

import java.awt.*;
public class TestUnicode extends java.applet.Applet {

public static final String COPYRIGHT = "\u00a9";


public static final String REGISTERED = "\u00ae";
public static final String EURO = "\u20ac";

public void init () {


setLayout(new FlowLayout());
Label a = new Label(COPYRIGHT + " R\u00e9al Gagnon");
Label b = new Label(REGISTERED + " R\u00e9al's Software "
+ " price : 100 " + EURO);

Display "special character" using Unicode 247


Real's HowTo PDF version

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
â \u00e2 Â \u00c2
é \u00e9 É \u00c9
è \u00e8 È \u00c8
ê \u00ea Ê \u00ca
î \u00ee Î \u00ce
ç \u00e7 Ç \u00c7
The Indian rupee symbol ( ₹ HTML entity : &#x20B9;) is quite new (2010) so you need to make sure that
the Font that you are using has it. To display it from Java, you need to use Swing because AWT won't be able
to display it.
import java.awt.*;
import javax.swing.*;

public class TestUnicode extends JApplet {


public static final String RUPEE = "\u20B9";

public void init () {


setLayout(new FlowLayout());

JLabel b = new JLabel("rupee : " + RUPEE);


b.setFont(new Font("Arial", Font.PLAIN, 14));
add(b);
}
}

Display chinese/japanese characters in an Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0137.html

A useful link to integrate international characters set in Netscape is


http://developer.netscape.com/software/jdk/i18n.html and check also

Display chinese/japanese characters in an Applet 248


Real's HowTo PDF version

http://www.geocities.com/Tokyo/Pagoda/1675/ for a more complete overview.

Localize a JOptionPane dialog


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0138.html

This example will show 2 radio buttons, one for english messages and buttons and the other one for french.
Press the button to display a localized JOptionPane according to the radio button selected.

Create 2 properties files, one for english , one for french.

[JOptionPane_en.properties]
Yes=Yes
No=No
Cancel=Cancel
SaveMsg=Do you want to save your data

[JOptionPane_fr.properties]
Yes=Oui
No=Non
Cancel=Annuler
SaveMsg=Voulez-vous sauvegarder vos donnees

Then

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

public class MessageBoxExample extends JPanel


implements ActionListener {
JButton go;
AbstractButton button;
ButtonGroup group;
Locale locale;
String msg ;

public MessageBoxExample() {
group = new ButtonGroup();

locale = Locale.US; // default value


button = new JRadioButton("English", true);
button.setActionCommand("en");
button.addActionListener(this);
group.add(button);
add(button);

Localize a JOptionPane dialog 249


Real's HowTo PDF version

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

Localize a JOptionPane dialog 250


Real's HowTo PDF version

frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
}

Validate/Convert a number using the current Locale()


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0139.html

Depending on the International setting, numbers with comma as decimal separator may be permitted. The
NumberFormat class can handle this based on the current Locale().

import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;

public class NumberUtils {

private 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());
System.out.println(NumberUtils.getDoubleValue("42,24"));
System.out.println(NumberUtils.getDoubleValue("42.24"));
System.out.println(NumberUtils.convertStringAsStringNumberUnLocalized

Validate/Convert a number using the current Locale() 251


Real's HowTo PDF version

(new Locale("fr"), "42,24"));


/*
* output
* fr_CA
* 42.24
* 42.0
* 42.24
*/
}
}

Localize a JFileChooser
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0299.html

Modern Swing release have now built-in ready-to-use translations for the JFileChooser. The language is
choosen based on the current Locale. So you don't have to do anything to display the JFileChooser in the right
language.

The user interface elements provided by the J2SE Runtime Environment 5.0, include Swing dialogs, messages
written by the runtime environment to the standard output and standard error streams, as well as messages
produced by the tools provided with the JRE. These user interface elements are localized into the following
languages:

Language Locale ID
Chinese (Simplified) zh_CN
Chinese (Traditional) zh_TW
English en
French fr
German de
Italian it
Japanese ja
Korean ko
Spanish es
Swedish sv
Sun Supported Locales

This example will show 2 radio buttons, one for english, one for french. Press the button to display a localized
JFileChooser according to the radio button selected.

Localize a JFileChooser 252


Real's HowTo PDF version

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 javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class LocalizeJFileChooser extends JPanel


implements ActionListener {
JButton go;
AbstractButton button;
ButtonGroup group;
Locale locale;
String msg ;

protected JFileChooser z_chooser;


String z_choosertitle;

public LocalizeJFileChooser() {
group = new ButtonGroup();

locale = Locale.US; // default value


button = new JRadioButton("English", true);
button.setActionCommand("en");
button.addActionListener(this);
group.add(button);
add(button);

button = new JRadioButton("Francais");


button.setActionCommand("fr");
button.addActionListener(this);
group.add(button);

Localize a JFileChooser 253


Real's HowTo PDF version

add(button);

go = new JButton("Do it");


go.addActionListener(this);
add(go);

locale = Locale.US;

public void setUILanguage() {


ResourceBundle rb;
rb = ResourceBundle.getBundle("JFileChooser", locale);

z_choosertitle = rb.getString("Title");

UIManager.put
("FileChooser.lookInLabelText",
rb.getString("lookInLabelText"));
UIManager.put
("FileChooser.filesOfTypeLabelText",
rb.getString("filesOfTypeLabelText"));
UIManager.put
("FileChooser.upFolderToolTipText",
rb.getString("upFolderToolTipText"));
/*
do the same with :
FileChooser.fileNameLabelText
FileChooser.homeFolderToolTipText
FileChooser.newFolderToolTipText
FileChooser.listViewButtonToolTipTextlist
FileChooser.detailsViewButtonToolTipText
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;

Localize a JFileChooser 254


Real's HowTo PDF version

if (e.getSource() instanceof JRadioButton) {


if (e.getActionCommand().equals("en"))
locale = Locale.US;
else
locale = Locale.FRANCE;
setUILanguage();
}
else {
z_chooser = new JFileChooser();
z_chooser.setCurrentDirectory(new java.io.File("."));
z_chooser.setDialogTitle(z_choosertitle);
if (z_chooser.showOpenDialog(this) !=
JFileChooser.APPROVE_OPTION)
return;
}
}

public Dimension getPreferredSize(){


return new Dimension(200, 200);
}

public static void main(String s[]) {


JFrame frame = new JFrame("");
LocalizeJFileChooser panel = new LocalizeJFileChooser();
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
}

Disable localization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0418.html

By default, the JVM uses the current locale as defined by the OS. To bypass this configuration, you specify on
the command line the locale to be used :

java -Duser.language=en -Duser.region=US MyApplication

Disable localization 255


Real's HowTo PDF version

Generate the Javadoc "en français"


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0437.html

The javadoc utility uses the regular Java mechanism to internationalize its output. The tools.jar in the lib
directory contains the resource bundle standard.properties used by Javadoc to generated the labels. To add a
new language, you need to create the appropriate resource bundle, in our case for french, we need a file called
standard_fr.properties.

The new file must be in the package com.sun.tools.doclets.standard.resources.

Extract from tools.jar, the standard.properties files (keep the directory structure). Copy it under the name
standard_fr.properties. Translate it (or you can download my "incomplete" version here).

[standard.properties (extract)]

doclet.Window_Split_Index={0}\: {1}-Index
doclet.Packages=Packages
doclet.SerialData=Serial Data\:
doclet.Since=Since\:
doclet.Warn_inline_taglet=Inline tag {0} should only be used with a {1}.
doclet.ClassUse_Subinterface=Subinterfaces of {0} in {1}
doclet.Frame_Version=Frame version
doclet.Generated_Docs_Untitled=Generated Documentation (Untitled)

[standard_fr.properties (extract)]

doclet.Window_Split_Index={0}\: {1}-Index
doclet.Packages=Paquetages
doclet.SerialData=Donn\u00E9e s\u00E9rialis\u00E9e\:
doclet.Since=Depuis\:
doclet.Warn_inline_taglet=Inline tag {0} should only be used with a {1}.
doclet.ClassUse_Subinterface=Sous-interfaces de {0} dans {1}
doclet.Frame_Version=Version avec cadres
doclet.Generated_Docs_Untitled=Documentation g\u00E9n\u00E9r\u00E9e

Once everything translated, put your standard_fr.properties into the tools.jar making sure that the file is
located in the right package (along standard.properties in 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,

Generate the Javadoc "en français" 256


Real's HowTo PDF version

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

Sort an array with international characters


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0343.html

Sort utilities are now part of latest JDK versions.

Case sensitive

java.util.Arrays.sort(myArray);

Case insensitive

java.util.Arrays.sort(myArray, String.CASE_INSENSITIVE_ORDER);

Sort with international characters.

Take the following example :

import java.util.*;
import java.io.*;

public class TestSort1 {

static String [] words = { "Réal", "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);

Sort an array with international characters 257


Real's HowTo PDF version

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;
}
else {
return System.console().writer();
}
}
}

The output is :

Before :
Réal Real Raoul Rico
After :
Raoul Real Rico Réal

which is wrong since we expect to find "Réal" after "Real".

To solve the problem , replace

java.util.Arrays.sort(words);

by

java.util.Arrays.sort(words, java.text.Collator.getInstance(java.util.Locale.FRENCH));
// or
// java.util.Arrays.sort(words, java.text.Collator.getInstance());

and the output will be :

Before :
Réal Real Raoul Rico

Sort an array with international characters 258


Real's HowTo PDF version

After :
Raoul Real Réal 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

Accentuated characters in Properties/ResourceBundle file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0492.html

The rules are

• Only use ISO Latin 1 characters in the Properties/ResourceBundle files


• For other characters use the \u.... notation
• To avoid having to type all the \u... notation manually, use the native2ascii tool (included with the
SDK).

Compare accentuated letters


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0496.html

Accentuated characters in Properties/ResourceBundle file 259


Real's HowTo PDF version

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

Compare accentuated letters 260


Real's HowTo PDF version

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 = "Réal";

System.out.println(a + " and " + b + " equals? " +


check(a,b));
/*
* output :
* Real and Réal equals? true
*/
}

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.

Remove accent from letters (ex .é to e)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0456.html

Remove accent from letters (ex .é to e) 261


Real's HowTo PDF version

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.

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 US-ASCII 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 _ @
}
}

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.replaceAll("[èéêë]","e");
s = s.replaceAll("[ûù]","u");
s = s.replaceAll("[ïî]","i");
s = s.replaceAll("[àâ]","a");
s = s.replaceAll("Ô","o");

s = s.replaceAll("[ÈÉÊË]","E");

Remove accent from letters (ex .é to e) 262


Real's HowTo PDF version

s = s.replaceAll("[ÛÙ]","U");
s = s.replaceAll("[ÏÎ]","I");
s = s.replaceAll("[ÀÂ]","A");
s = s.replaceAll("Ô","O");

System.out.println(s);
// output : E,E,E,E,U,U,I,I,A,A,O,e,e,e,e,u,u,i,i,a,a,o
}
}

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

Remove accent from letters (ex .é to e) 263


Real's HowTo PDF version

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

public static String toUpperCaseSansAccent(String txt) {


if (txt == null) {

Remove accent from letters (ex .é to e) 264


Real's HowTo PDF version

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

Output accentuated characters to the console


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0046.html

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 = "caractères français : à é \u00e9"; // Unicode for "é"
System.out.println(s);
System.console().writer().println(s);
}
}

anf the output is

Output accentuated characters to the console 265


Real's HowTo PDF version

C:\temp>java Test
caractþres franþais : Ó Ú Ú
caractères français : à é é

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 =
"caractères français : à é \u00e9"; // Unicode for "é"

try {
ps = new PrintStream(System.out, true, "Cp850");
}
catch (UnsupportedEncodingException error) {
System.err.println(error);
System.exit(0);
}
ps.println(javaString);
}
}

Note : List of supported encodings here

Get the default character set of the JVM


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0505.html

public class Hello {


public static void main(String args[]) throws Exception{
// not crossplateform safe
System.out.println(System.getProperty("file.encoding"));
// jdk1.4
System.out.println(
new java.io.OutputStreamWriter(
new java.io.ByteArrayOutputStream()).getEncoding()
);
// jdk1.5

Output accentuated characters to the console 266


Real's HowTo PDF version

System.out.println(java.nio.charset.Charset.defaultCharset().name());
}
}

Output example (winXP)

>java Hello
Cp1252
Cp1252
windows-1252

See also java encoding table for the encoding sets supported.

Convert OEM (DOS) file to Ansi (Windows)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0524.html

We are using an InputStreamReader which convert the specified input encoding to Unicode and an
OutputStreamWriter which from Unicode to the specified output encoding.

This can be useful when migrating data from a legacy database (ex. Clipper, dBase) to newer DBMS (ex.
mySQL, Sybase).

import java.io.*;

public class OemToAnsi {

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


if (args.length != 2) {
System.out.println(
"Usage : java OemToAnsi inputdosfile outputansifile"
);
System.out.println(
" note : codepage input Cp850 codepage output Cp1252"
);
System.exit(1);
}
// input
FileInputStream fis = new FileInputStream(args[0]);
BufferedReader r =
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);

Get the default character set of the JVM 267


Real's HowTo PDF version

w.flush();
}
w.close();
r.close();
System.exit(0);
}
}

See also this related HowTo

Detect non-ASCII character in a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0536.html

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharacterCodingException;

public class StringUtils {


private StringUtils() {}

public static boolean isPureAscii(String v) {


byte bytearray [] = v.getBytes();
CharsetDecoder d = Charset.forName("US-ASCII").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 = "Réal";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));
test = "Real";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));
/*
* output :
* Réal isPureAscii() : false
* Real isPureAscii() : true
*/
}
}

Convert OEM (DOS) file to Ansi (Windows) 268


Real's HowTo PDF version

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("US-ASCII").newEncoder(); // or "ISO-8859-1" for ISO Latin 1

public static boolean isPureAscii(String v) {


return asciiEncoder.canEncode(v);
}

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


String test = "Réal";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));
test = "Real";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));

/*
* output :
* Réal isPureAscii() : false
* Real isPureAscii() : true
*/
}
}

Another way is to use a regular expression, see this Javascript HowTo for a hint!

To simply strip any non-ascii characters form a string


public class Test {
public static void main(String args[]){
String input = "eéaà";
String output = input.replaceAll("[^\\p{ASCII}]", "");
System.out.println(output);
/*
* output : ea
*/
}
}

See also Unaccent letters.

Get the month (or day) name (localized)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0650.html

Detect non-ASCII character in a String 269


Real's HowTo PDF version

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

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 Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Get the month (or day) name (localized) 270


IO
java-io

Redirect output(stdout/stderr) to a frame


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0028.html

[JDK1.1]

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

public class RedirectedFrame extends Frame {


TextArea aTextArea = new TextArea();
PrintStream aPrintStream =
new PrintStream(
new FilteredStream(
new ByteArrayOutputStream()));

boolean logFile;

RedirectedFrame(boolean logFile) {
this.logFile = logFile;
System.setOut(aPrintStream);
System.setErr(aPrintStream);
setTitle("Error message");
setSize(500,300);
setLayout(new BorderLayout());
add("Center" , aTextArea);
displayLog();
addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose();
}
}
);
}

class FilteredStream extends FilterOutputStream {


public FilteredStream(OutputStream aStream) {
super(aStream);
}

public void write(byte b[]) throws IOException {


String aString = new String(b);

IO 271
Real's HowTo PDF version

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

Redirect printStackTrace() to a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0029.html

import java.io.*;

public class TestStack2String {


public static void main(String s[]){
try {
// force an exception for demonstration purpose

Redirect output(stdout/stderr) to a frame 272


Real's HowTo PDF version

Class.forName("unknown").newInstance();
// or this could be changed to:
// throw new Exception();

}
catch (Exception e) {
System.out.println(stack2string(e));
}
}

public static String stack2string(Exception e) {


try {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
return "------\r\n" + sw.toString() + "------\r\n";
}
catch(Exception e2) {
return "bad stack2string";
}
}
}

Redirect to NULL device


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0453.html

This can be useful if you want to suppress all output.

// Unix style
PrintStream nps = new PrintStream(new FileOutputStream("/dev/null"));
System.setErr(nps);
System.setOut(nps);

//Windows style
PrintStream nps = new PrintStream(new FileOutputStream("NUL:"));
System.setErr(nps);
System.setOut(nps);

//One-liner style : subclass OutputStream to override the write method ...


System.setOut(new java.io.PrintStream(
new java.io.OutputStream() {
public void write(int b){}
}
));

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.

Redirect printStackTrace() to a String 273


Real's HowTo PDF version

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

Print a text file using the javax.print API


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-print-a-text-file-with-javax.print-api.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 "OCTET-STREAM" 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 java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.File;
import java.io.FileInputStream;

import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import 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 {

Redirect to NULL device 274


Real's HowTo PDF version

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 = new HashPrintRequestAttributeSet();


pras.add(new Copies(1));

DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;


Doc doc = new SimpleDoc(in, flavor, null);

DocPrintJob job = service.createPrintJob();


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

Print a text file using the javax.print API 275


Real's HowTo PDF version

}
});
}
public synchronized void waitForDone() {
try {
while (!done) {
wait();
}
} catch (InterruptedException e) {
}
}
}

To print a String, see this HowTo

Print a String using the javax.print API


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-print-a-string-using-javax-print-api.html

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import 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"));

Print a String using the javax.print API 276


Real's HowTo PDF version

PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();


pras.add(new Copies(1));

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

Print a String using the javax.print API 277


Real's HowTo PDF version

Print text to a printer easily


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0051.html

A quick and simple way to output some text to a printer is to print to OS logical device attached a printer.

For example, on a Windows machine :

import java.io.FileWriter;

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

Print without a Dialog


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0350.html

JobAttributes theJobAttribs = new JobAttributes();


PageAttributes thePageAttribs = new PageAttributes();

theJobAttribs.setDialog(JobAttributes.DialogType.NONE);
theJobAttribs.setPrinter("HP DeskJet 610C"); // the printer to be used
PrintJob myJob = getToolkit().getPrintJob(this, "PrintJob", theJobAttribs, thePageAttribs);

if (myJob != null) {
Graphics g = myJob.getGraphics();
if (g != null) {
String s = myArea.getText(); // what you like to print
printText(myJob, g, s);
g.dispose();
}
}
myJob.end();

Print text to a printer easily 278


Real's HowTo PDF version

Initialize and write to a serial port


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0062.html

This is for JAVA application only (JDK1.1).

(Win)Initialization is done via the MODE.COM utility. Then to write, simply open a stream using the OS
logical name attached to the serial port. You can use the same technique to print to the printer port (in this
case the local name would be "LPTx:").

public class SerialTest {


public static void main( String args[]) {
Runtime rt = Runtime.getRuntime();
Process p = null;
String portname = "com1:";
// for Win95 : c:\\windows\\command.com
// c:\\windows\\command\\mode.com
String cmd[] = {
"c:\\winnt\\system32\\cmd.exe", "/c",
"start", "/min",
"c:\\winnt\\system32\\mode.com", portname,
"baud=9600", "parity=n", "data=8",
"stop=1",
};
try {
p = rt.exec( cmd );
if( p.waitFor() != 0 ) {
System.out.println("Error executing command: " + cmd );
System.exit( -1 );
}
byte data[] =
"Writing a byte stream out of a serial port.".getBytes();
FileOutputStream fos = new FileOutputStream( portname );
BufferedOutputStream bos = new BufferedOutputStream( fos );
fos.write( data, 0, data.length );
fos.close();
}
catch( Exception e ) {
e.printStackTrace();
}
}
}

Open or close a CD/DVD drive


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0574.html

Initialize and write to a serial port 279


Real's HowTo PDF version

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

Open or close a CD/DVD drive 280


Real's HowTo PDF version

}
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

Get the volume label


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0455.html

This will retrieve the hard disk volume label :

import java.io.*;
import javax.swing.filechooser.*;

public class VolumeLabel {


private VolumeLabel() { }

public static void main(String[] args) {


System.out.println("\"" + get(args[0]) + "\"");
}

public static String get(String path) {


FileSystemView view = FileSystemView.getFileSystemView();
File dir = new File(path);
String name = view.getSystemDisplayName(dir);
if (name == null) { return null; }
name = name.trim();
if (name == null || name.length() < 1) {
return null;
}
int index = name.lastIndexOf(" (");
if (index > 0) {
name = name.substring(0, index);
}
return name;

Get the volume label 281


Real's HowTo PDF version

}
}

The output

Running from c:\temp

>java VolumeLabel c:
"temp"

>java VolumeLabel c:\


"HARDDISK1"

Detect the storage device type


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0635.html

javax.swing.filechooser.FileSystemView provides a way to detect the type of a particular device.

import java.io.File;
import java.util.Arrays;
import java.util.List;
import 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);
}
/* 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 java.io.File;
import java.util.Arrays;
import java.util.List;

Detect the storage device type 282


Real's HowTo PDF version

import 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:)
*/

}
}

Turn on MQ Debug mode


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-turn-on-mq-debug-mode.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.

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

Get faster console output (System.out.println() replacement)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0603.html

Turn on MQ Debug mode 283


Real's HowTo PDF version

If your program is doing a lot printing to the console using System.out.println() then it is possible to get a
good performance boost by using an alternative to do the console output.

By default, System.out.print() is only line-buffered and does a lot work related to Unicode handling.
Because of its small buffer size, System.out.println() is not well suited to handle many repetitive outputs in
a batch mode. Each line is flushed right away. If your output is mainly ASCII-based then by removing the
Unicode-related activities, the overall execution time will be better.

Consider this program :

import java.io.BufferedWriter;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;

public class Test {


public static void main(String...args) throws Exception {
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
System.out.print("abcdefghijk ");
System.out.print(String.valueOf(i));
System.out.print('\n');
}
System.err.println("Loop time: " +
(System.currentTimeMillis() - start));
}
}

The result is

>java Test >NUL


Loop time: 7000

Now, rewrite this program to use a 512-bytes buffer and specify the ASCII as character-encoding to be
used.

import java.io.BufferedWriter;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;

public class Test {


public static void main(String...args) throws Exception {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new
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');

Get faster console output (System.out.println() replacement) 284


Real's HowTo PDF version

}
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.

Simple input from the keyboard


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0053.html

First method

import java.io.*;
public class TestReadLine {
public static void main (String args[]) {
StreamTokenizer Input=new StreamTokenizer(System.in);
try {
System.out.print(" Your first name : ");
Input.nextToken();
System.out.println("Hi " + Input.sval + "!");
}
catch (Exception e) {
e.printStackTrace();
}
}
}

Second method JDK1.0.2

java.io.DataInputStream in =
new java.io.DataInputStream(System.in);
String aLine = in.readLine();

Third method JDK1.1


In you program, use EasyInput.inputStr("<prompt>") to input a String or EasyInput.InputInt("<prompt>")
for an integer.

Simple input from the keyboard 285


Real's HowTo PDF version

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.

Output french character to the console


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0046.html

Output french character to the console 286


Real's HowTo PDF version

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 = "caractères français : à é \u00e9"; // Unicode for "é"
System.out.println(s);
System.console().writer().println(s);
}
}

anf the output is

C:\temp>java Test
caractþres franþais : Ó Ú Ú
caractères français : à é é

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 =
"caractères français : à é \u00e9"; // Unicode for "é"

try {
ps = new PrintStream(System.out, true, "Cp850");
}
catch (UnsupportedEncodingException error) {
System.err.println(error);
System.exit(0);
}
ps.println(javaString);
}
}

Note : List of supported encodings here

Output french character to the console 287


Real's HowTo PDF version

Clear the console and control attributes


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0047.html

There is no built-in way to really control character-based 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.

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 String ANSI_CLS = "\u001b[2J";
public static final String ANSI_HOME = "\u001b[H";
public static final String ANSI_BOLD = "\u001b[1m";
public static final String 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();

Clear the console and control attributes 288


Real's HowTo PDF version

}
}

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.

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 64-bit OS you need to use JCurses with a 32-bit
JVM).

This example will display a character-based window with a label, a textfield and a button (don't click with
you mouse, use the keyboard!).

import jcurses.system.*;
import jcurses.widgets.*;
import jcurses.util.*;
import 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());

Clear the console and control attributes 289


Real's HowTo PDF version

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

Easy keyboard input (JDK1.5)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0491.html

import java.util.Scanner;

Easy keyboard input (JDK1.5) 290


Real's HowTo PDF version

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.

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

Easy keyboard input (JDK1.5) 291


Real's HowTo PDF version

Force keyboard input in CAPS LOCK on


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


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

Force keyboard input in CAPS LOCK on 292


Real's HowTo PDF version

NOTE : This technique changes the keyboard state so the effect is also seen outside the Java program.

See also this related Howto.

Automatic conversion of System.out output


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-automatic-conversion-of-System.out-output.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) {
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();

Automatic conversion of System.out output 293


Real's HowTo PDF version

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

Execute an external program and capture the output


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0014.html

Be sure to read this Javaworld article. It describes the various pitfalls related to the Runtime.exec()
method.

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

Execute an external program and capture the output 294


Real's HowTo PDF version

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

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

Execute an external program and capture the output 295


Real's HowTo PDF version

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

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

test.cmd (set the errorlevel 0 (execution Ok)

@java -version

Launch a Unix script

String[] cmd = {"/bin/sh", "-c", "ls > hello"};


Runtime.getRuntime().exec(cmd);

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

Execute an external program and capture the output 296


Real's HowTo PDF version

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

Windows rundll32 utility

Windows File association


Any program using the Windows file association mechanism can be started with the rundll32 utility.

// "file" is the filename of the data file


// ex. myresume.doc
// to start Word if the doc extension is associated with it.
Runtime.getRuntime().exec
("rundll32 SHELL32.DLL,ShellExec_RunDLL " + file.getAbsolutePath());

See also this HowTo about the new Desktop API, the recommended solution (but you need JDK1.6).
See also this one to open the default browser.

The following example start a Dial-up connection on the Win plateform :

[Dialup.java]
public class Dialup {
public static void main(String[] args) throws Exception {
Process p = Runtime.getRuntime()
.exec("rundll32.exe rnaui.dll,RnaDial MyConnection");
p.waitFor();
System.out.println("Done.");
}
}

Execute an external program and capture the output 297


Real's HowTo PDF version

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

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

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

Path to executable with spaces in them

You can include a path for the program to be executed. On the Win plateform, you need to put the path in
quotes if the path contains spaces.

public class Test {


public static void main(String[] args) throws Exception {
Process p = Runtime.getRuntime().exec(
"\"c:/program files/windows/notepad.exe\"");
p.waitFor();
}
}

If you need to pass arguments, it's safer to a String array especially if they contain spaces.

String[] cmd = { "myProgram.exe", "-o=This is an option" };


Runtime.getRuntime().exec(cmd);

Execute an external program and capture the output 298


Real's HowTo PDF version

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

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

HTML Help (Windows only)

Runtime.getRuntime().exec("hh.exe myhelpfile.chm");

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

Execute an external program and capture the output 299


Real's HowTo PDF version

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.

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.

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 {

Execute an external program and capture the output 300


Real's HowTo PDF version

String[] commands =
{"cmd.exe",
"/c",
WIN_PROGRAMFILES
+ FILE_SEPARATOR
+ "textpad 4"
+ 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/windows-vista-junctions-points-mui-and-localized-folder-nam

Launch the application associated with a file extension


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0579.html

JDK1.6
The java.awt.Desktop class uses your host operating system's file associations to launch applications
associated with specific file types.

First it's a good idea to check if the Desktop operations are supported on the running plateform.

import java.awt.*;
...

if (Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
for (Desktop.Action action : Desktop.Action.values()) {
System.out.println("action " + action + " supported? "
+ desktop.isSupported(action));
}
}

The possible actions are


• BROWSE. launching the user-default browser to show a specified URI
• MAIL. launching the user-default mail client with an optional mailto URI;
• OPEN. launching a registered application to open a specified file.
• EDIT. launching a registered application to edit a specified file.
• PRINT. launching a registered application to print a specified file.

then

Launch the application associated with a file extension 301


Real's HowTo PDF version

// application associated to a file extension


public static void open(File document) throws IOException {
Desktop dt = Desktop.getDesktop();
dt.open(document);
}

public static void print(File document) throws IOException {


Desktop dt = Desktop.getDesktop();
dt.print(document);
}

// default browser
public static void browse(URI document) throws IOException {
Desktop dt = Desktop.getDesktop();
dt.browse(document);
}

// default mail client


// use the mailto: protocol as the URI
// ex : mailto:[email protected]?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.

Launch an application from another application


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0394.html

While you can exec("java myanotherapp"), 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[]) {

Launch an application from another application 302


Real's HowTo PDF version

System.out.println("Hello from Program1a");


new Thread(){
public void run() {
Program2.main(new String[]{});}
}.start();
}

The above example is used when the class is hard-coded.

The dynamic version is little more tricky.

public class Program1b {


public static void main(String arg[]) {
System.out.println("Hello from Program1b");
new Program1b().execute("Program2");
}

public void execute(String name) {


Class params[] = {String[].class};
// if you need parameters
// String[] args = new String[] { "Hello", "world" };
// Class params[] = new Class[] { args.getClass() });
try {
Class.forName(name).
getDeclaredMethod("main", params).
invoke(null, new Object[] {new String[] {}});
}
catch(Exception e){ e.printStackTrace();}
}
}

Launch many programs using Thread and use join() to wait for the completion.

[Program2.java]
public class Program2 {
public static void main(String arg[]) {
System.out.println("Hello from Program2");
System.out.println("Hello from Program2");
System.out.println("Hello from Program2");
System.out.println("Hello from Program2");
}
}

[Program1a.java]
public class Program1a {
public static void main(String arg[]) throws Exception{
System.out.println("Hello from Program1a");
Thread t1 = new Thread(){
public void run() {
Program2.main(new String[]{});}
};

Launch an application from another application 303


Real's HowTo PDF version

t1.start();
t1.join();
System.out.println("Hello from Program1a");
}
}

The output :

C:\>java Program1a
Hello from Program1a
Hello from Program2
Hello from Program2
Hello from Program2
Hello from Program2
Hello from Program1a

Start the default browser from an application


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0071.html

In this snippet, we initialize a Listbox from a file containing some URLs. When we double click an item,
the default browser is started with the selected HTML page as parameter. This example is Windows
oriented since I have used the start command which supports the file association.

[urlList.txt]

http://www.rgagnon.com/javadetails/java-0001.html|JAVA How-to 1
http://www.rgagnon.com/javadetails/java-0002.html|JAVA How-to 2
http://www.rgagnon.com/javadetails/java-0003.html|JAVA How-to 3
http://www.rgagnon.com/javadetails/java-0004.html|JAVA How-to 4
http://www.rgagnon.com/javadetails/java-0005.htmL|JAVA How-to 5

[StartBrowser.java]

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

public class StartBrowser {


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

class AFrame extends Frame implements ActionListener {


List lbx;

Start the default browser from an application 304


Real's HowTo PDF version

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

Start the default browser from an application 305


Real's HowTo PDF version

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

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.

Execute a Windows Shortcut (.lnk)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0571.html

A Shortcut is stored in a file with the extension lnk.

Execute a Windows Shortcut (.lnk) 306


Real's HowTo PDF version

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

Create a file association with a Java program


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0592.html

In this example, a file with the extension .xox will be defined and associated with a java program (display
the first 10 lines of selected .xox file).

First the java program to be associated with the .xox file type.

import java.io.*;

public class Head {


static final int MAX_LINES = 10;
public static void main(String args[]) throws Exception{
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.

Create a file association with a Java program 307


Real's HowTo PDF version

To know more about these commands, type assoc /? or ftype /? .

First we define the .xox file type.

The assoc command sets up an association between a file name extension and a file type.

>assoc .xox=Xoxfile
.xox=Xoxfile

Then we specify which program is used to handle the Xoxfile type of file.

The ftype command sets up an association between a file type name, and a string to be used to execute it.

In this example, we specify the Java JVM to be used, the classpath to load the Head.class plus the
parameter (the selected .xox file).

>ftype Xoxfile=C:\Program Files\Java\jre1.5.0\bin\java -cp c:\dev\work Head %1


Xoxfile=C:\Program Files\Java\jre1.5.0\bin\java -cp c:\dev\work Head %1

Now, if you double-click on a file with .xox extension, a Dos shell is opened, the Head class is launched
with the clicked filename as a parameter and the first 10 line are displayed.

To make the file association works from a command line, you define the environment variable PATHEXT
to include the .xox extension.

>set pathext=.xox;%pathext%
PATHEXT=.XOX;.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH

then you will be able, from a Dos shell, to type only the name of .xox file and the associated program will
be launched with that file as a parameter.

See also this HowTo.

Capture the output from a VBS


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0576.html

This HowTo query the Windows Registry for a specific key. The VBS prints the result and from Java, we
capture this output.

Since we need the output, we must use the VBS interpreter for the console mode (CSCRIPT.EXE).

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;

Capture the output from a VBS 308


Real's HowTo PDF version

import java.io.InputStreamReader;

public class VBSUtils {


private VBSUtils() { }

public static String readWindowRegistry(String key) {


String result = "";
try {

File file = File.createTempFile("realhowto",".vbs");


file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);

String vbs = "Dim WSHShell \n"


+ "Set WSHShell = WScript.CreateObject(\"WScript.Shell\") \n"
+ "WScript.Echo _ \n"
+ "WSHShell.RegRead(\"" + key + "\") \n"
+ "Set WSHShell = Nothing \n";
fw.write(vbs);
fw.close();
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
BufferedReader input =
new BufferedReader
(new InputStreamReader(p.getInputStream()));
String line;
while ((line = input.readLine()) != null) {
result += line;
}
input.close();
}
catch(Exception e){
e.printStackTrace();
}
return result.trim();
}

public static void main(String[] args){


//
// DEMO
//
String result = "";
msgBox("Get the path of Acrobat reader from the registry");
result = readWindowRegistry
("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\AcroRd32.exe\\");
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);
}
}

Capture the output from a VBS 309


Real's HowTo PDF version

Get a return code from a VBS


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0575.html

You can't detect directly if Windows service is running or not in Java.

However, it's easy to do from a VBS. You execute the script from Java, wait for its completion and capture
the return code.

Obviously, this is useful only on the Windows plateform.

import java.io.File;
import java.io.FileWriter;

public class VBSUtils {


private VBSUtils() { }

public static boolean isServiceRunning(String serviceName) {


try {
File file = File.createTempFile("realhowto",".vbs");
file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);

String vbs = "Set sh = CreateObject(\"Shell.Application\") \n"


+ "If sh.IsServiceRunning(\""+ serviceName +"\") Then \n"
+ " wscript.Quit(1) \n"
+ "End If \n"
+ "wscript.Quit(0) \n";
fw.write(vbs);
fw.close();
Process p = Runtime.getRuntime().exec("wscript " + file.getPath());
p.waitFor();
return (p.exitValue() == 1);
}
catch(Exception e){
e.printStackTrace();
}
return false;
}

public static void main(String[] args){


//
// DEMO
//
String result = "";
msgBox("Check if service 'Themes' is running (should be yes)");
result = isServiceRunning("Themes") ? "" : " NOT ";
msgBox("service 'Themes' is " + result + " running ");

Get a return code from a VBS 310


Real's HowTo PDF version

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

Execute a CMD file stored in a JAR


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0600.html

In this example, a CMD file is stored a JAR file. The Java code extracts the file as a ressource, launch a
Windows CMD Shell and write the content to the stdin without any temporary file.

In this How-to, the CMD included is used to trigger the default Windows screen saver.

scrnsave.scr /s

import java.io.*;

public class StartScreenSaver {


public static void main(String args[]) throws IOException {
new StartScreenSaver().doit();
}

public void doit() throws IOException{


String line;
OutputStream stdin = null;
InputStream stderr = null;
InputStream stdout = null;

try {
// that our CMD file in our JAR
InputStream is =
getClass().getResource("/screensaver.cmd").openStream();
BufferedReader brCmdLine =
new BufferedReader(new InputStreamReader(is));

// launch CMD and grab stdin/stdout and stderr


Process process = Runtime.getRuntime ().exec ("cmd");
stdin = process.getOutputStream ();
stderr = process.getErrorStream ();
stdout = process.getInputStream ();

Execute a CMD file stored in a JAR 311


Real's HowTo PDF version

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

Open the default file explorer


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-open-default-os-file-explorer.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[]) {

Open the default file explorer 312


Real's HowTo PDF version

Desktop desktop = null;


// on Windows, retrieve the path of the "Program Files" folder
File file = new File(System.getenv("programfiles"));

try {
if (Desktop.isDesktopSupported()) {
desktop = Desktop.getDesktop();
desktop.open(file);
}
else {
System.out.println("desktop is not supported");
}
catch (IOException e){ }
}
}

Read the content of a file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0052.html

From a Java application

This following example is for an application.

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;

public class Cat {


public static void main (String args[]) throws Exception {
String line;
FileInputStream fin = null;
BufferedReader br = null;
InputStreamReader isr = null;

try {
fin = new FileInputStream("D:/temp/howto.txt");
isr = new InputStreamReader(fin);
br = new BufferedReader(isr);
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
finally {
if (br != null) br.close();
if (isr != null) isr.close();
if (fin != null) fin.close();
}
}

Read the content of a file 313


Real's HowTo PDF version

The following method read a data file and return the content as a String. We use a StringBuilder to optimize
string concatenation operations.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Cat {


public static final String EOL = System.getProperty("line.separator");

private static String readFile(String filename) throws IOException {


BufferedReader br = null;
FileReader fr = null;

try {
fr = new FileReader(filename);
br = new BufferedReader(fr);
String nextLine = "";
StringBuilder sb = new StringBuilder();
while ((nextLine = br.readLine()) != null) {
sb.append(nextLine); // note: BufferedReader strips the EOL character
// so we add a new one!
sb.append(EOL);
}
return sb.toString();
}
finally {
if (br != null) br.close();
if (fr != null) fr.close();
}
}

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


System.out.println(readFile("d:/temp/howto.txt"));
}
}

JDK1.5 provides the java.util.Scanner class which can be used to quickly read a file.

The delimeter "\Z" represents the end-of-file 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);

Read the content of a file 314


Real's HowTo PDF version

scanner.close();
}
}

JDK7+ provides, with the NIO package, a new way to get all the content of file quickly. You don't need to
close anything because readAllLines() is taking care of that.

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

public class Cat {


public static void main (String args[]) throws Exception {
Path path = Paths.get( "d:/temp/howto.txt" );
List <String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
for (String element : lines) {
System.out.println(element);
}
}
}

See this HowTo to read a file stored in a JAR.

Read a text file from a Jar


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0077.html

import java.io.*;
import java.util.*;

public class FileUtils{

public static List<String> readTextFromJar(String s) {


InputStream is = null;
BufferedReader br = null;
String line;
ArrayList<String> list = new ArrayList<String>();

try {
is = FileUtils.class.getResourceAsStream(s);
br = new BufferedReader(new InputStreamReader(is));
while (null != (line = br.readLine())) {
list.add(line);
}
}
catch (Exception e) {

Read a text file from a Jar 315


Real's HowTo PDF version

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

Create 2 datafiles.

datafile1.txt in the same directory as FileUtils.class (in the root) and datafile2.txt in a subdirectory called
test

[datafile1.txt]

datafile1 line 1
datafile1 line 2
datafile1 line 3
datafile1 line 4
datafile1 line 5

[/test/datafile2.txt]

datafile2 line 1
datafile2 line 2
datafile2 line 3
datafile2 line 4
datafile2 line 5

Create the jar with

Read a text file from a Jar 316


Real's HowTo PDF version

>"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 line 1
datafile1 line 2
datafile1 line 3
datafile1 line 4
datafile1 line 5
datafile2 line 1
datafile2 line 2
datafile2 line 3
datafile2 line 4
datafile2 line 5

Get the JAR here

With an Applet, it's the same technique

import java.applet.*;
import java.io.*;

public class ReadFromJar extends Applet{

public void init(){


readTextFromJar("datafile1.txt");
readTextFromJar("test/datafile2.txt");
}

public void readTextFromJar(String s) {


String thisLine;
try {
InputStream is = getClass().getResourceAsStream(s);
BufferedReader br = new BufferedReader
(new InputStreamReader(is));
while ((thisLine = br.readLine()) != null) {
System.out.println(thisLine);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}

Create the JAR

Read a text file from a Jar 317


Real's HowTo PDF version

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

Read a text file from the internet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-read-a-file-from-the-internet.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));
}
}

Extract a file from a Jar


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0429.html

The following snippet extract a file (mydb.mdb) from a jar.

import java.io.*;
import java.util.jar.*;

Read a text file from the internet 318


Real's HowTo PDF version

import java.util.zip.*;

public class ExtractFromJAR {

public void extractMyMDBromJAR(String dest){


try {
String home = getClass().getProtectionDomain().
getCodeSource().getLocation().toString().
substring(6);
JarFile jar = new JarFile(home);
ZipEntry entry = jar.getEntry("mydb.mdb");
File efile = new File(dest, entry.getName());

InputStream in =
new BufferedInputStream(jar.getInputStream(entry));
OutputStream out =
new BufferedOutputStream(new FileOutputStream(efile));
byte[] buffer = new byte[2048];
for (;;) {
int nBytes = in.read(buffer);
if (nBytes <= 0) break;
out.write(buffer, 0, nBytes);
}
out.flush();
out.close();
in.close();
}
catch (Exception e) {
e.printStackTrace();
}
}

public static void main(String args []){


new ExtractFromJAR().extractMyMDBFromJAR(".");
}

Grab this auto-run Jar if you want to try it.

To create an auto-run JAR, first create a manifest.mft

Manifest-Version: 1.0
Classpath: .\mydb.jar
Main-Class: ExtractFromJAR

Create the JAR

C:\jdk141\bin\jar cvfm mydb.jar manifest.mft ExtractFromJAR.class mydb.mdb

Run it ... and the mydb.mdb file should appear in the current directory.

Extract a file from a Jar 319


Real's HowTo PDF version

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

Read a data file with floats


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0078.html

[ReadingFloat.java]

public class ReadingFloat {


public static float[] readFile(String file, String delimiter)
throws Exception {
return(readValues(new java.io.FileInputStream(file), delimiter));
}

public static float[] readURL(String url, String delimiter)


throws Exception {
java.net.URL addr = new java.net.URL(url);
return(readValues(addr.openStream(), delimiter));
}

public static float[] readValues(java.io.InputStream in, String delimiter)


throws java.io.FileNotFoundException,
java.io.IOException,
java.lang.NumberFormatException {
String thisLine;
java.io.BufferedInputStream s = new java.io.BufferedInputStream(in);
java.io.BufferedReader myInput = new java.io.BufferedReader
(new java.io.InputStreamReader(s));
int j = 0;
float[] values = new float[10];

while ((thisLine = myInput.readLine()) != null) {


// scan it line by line
java.util.StringTokenizer st =
new java.util.StringTokenizer(thisLine, delimiter);
while(st.hasMoreElements())
values[j++] = Float.valueOf(st.nextToken()).floatValue();

Read a data file with floats 320


Real's HowTo PDF version

}
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

Write to the end of a file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0054.html

[JDK1.0.2]

import java.io.*;
public class appendtext {
public static void main(String args[]){
try {
PrintStream out =
new PrintStream(new AppendFileStream("myfile"));

Write to the end of a file 321


Real's HowTo PDF version

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

Write "real" ascii file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0058.html

Java uses Unicode character encoding internally. To pass information to outside world, it may be necessary
to use different encoding.

For example, DOS application may use MS ISO-Latin 1(or Codepage 850) to represent french characters
like é or à.

Before writting to a file or in a database record it is necessary to change the default String encoding. This
done via the InputStreamReader class for input and OutputStreamWriter for output.

Write "real" ascii file 322


Real's HowTo PDF version

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 = "é &agrace; \u00e9"; // Unicode for "é"

try {
// output : Unicode to Cp850 (MS-DOS Latin-1)
FileOutputStream fos = new FileOutputStream("out.dat");
Writer w =
new BufferedWriter(new OutputStreamWriter(fos, "Cp850"));
w.write(JavaString);
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");.

Copy a file
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0064.html

[Java 7]

import static java.nio.file.StandardCopyOption.*;


import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

Copy a file 323


Real's HowTo PDF version

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^31-1 bytes. it throws an exception of "java.io.IOException: The parameter is incorrect"
In solaris8 , Bytes transfered to Target channel are 2^31-1 even if the source channel file is greater than 2^31-1
In LinuxRH7.1 , it gives an error of java.io.IOException: Input/output error

ref : http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4643189

On the Windows plateform, you can't copy a file bigger than 64Mb, an Exception in thread "main"
java.io.IOException: Insufficient system resources exist to complete the requested service is thrown.

Copy a file 324


Real's HowTo PDF version

For a discussion about this see :


http://forum.java.sun.com/thread.jspa?threadID=439695&messageID=2917510

The workaround is to copy in a loop 64Mb each time until there is no more data.

Replace

...
try {
inChannel.transferTo(0, inChannel.size(),
outChannel);
}
...

by

...
try {
// magic number for Windows, 64Mb - 32Kb)
int maxCount = (64 * 1024 * 1024) - (32 * 1024);
long size = inChannel.size();
long position = 0;
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();
}
}

Copy a file 325


Real's HowTo PDF version

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


FileUtils.copyFile(new File(args[0]),new File(args[1]));
}
}

Use a "log file"


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

private SimpleLog() { }

public static void setLogFilename(String filename) {


logFile = filename;
new File(filename).delete();

try {
write("LOG file : " + filename);
}
catch (Exception e) {
System.out.println(stack2string(e));
}

public static void write(String msg) {


write(logFile, msg);
}

public static void write(Exception e) {


write(logFile, stack2string(e));
}

public static void write(String file, String msg) {


try {
Date now = new Date();
String currentTime = SimpleLog.df.format(now);

Use a "log file" 326


Real's HowTo PDF version

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

and then to use it

SimpleLog.write("i am here");

See also this HowTo and this one

Delete files with a certain extension


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0072.html

Define a special FilenameFilter :

import java.io.*;

public class ExtensionFilter implements FilenameFilter {


private String extension;
public ExtensionFilter( String extension ) {
this.extension = extension;
}

public boolean accept(File dir, String name) {


return (name.endsWith(extension));
}
}

Delete files with a certain extension 327


Real's HowTo PDF version

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

Insert a line in a file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0073.html

The only way to insert a line in a text file is to read the original file and write the content in a temporary file
with the new line inserted. Then we erase the original file and rename the temporary file to the original
name.

In this example, you need to supply 3 arguments : the filename, a line number and the string to be inserted
at the line number specified.

java JInsert test.out 9 "HELLO WORLD"

will insert the string "HELLO WORLD" at line number 9 in the file "test.out".

of course you need more error checking...

[JDK1.1]
import java.io.*;

public class JInsert {

Insert a line in a file 328


Real's HowTo PDF version

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

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

Read a file into a variable in one shot


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0074.html

import java.io.*;

public class ReadFullyIntoVar {

Read a file into a variable in one shot 329


Real's HowTo PDF version

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

Serialize an object to a file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0075.html

Suppose we have a class called Queue.class. We want to save the state of the Queue in a file. Since our
Queue extends the Vector class, the methods needed to serialize the object are already done. All we need is
an input or output stream.

First the Queue class

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

Serialize an object to a file 330


Real's HowTo PDF version

Object peek() {
if (isEmpty()) return null;
return firstElement();
}
}

To serialize (save the Queue state to a file) :

public static void main(String args[]) {


Queue theQueue;

theQueue = new Queue();


theQueue.put("element 1");
theQueue.put("element 2");
theQueue.put("element 3");
theQueue.put("element 4");
System.out.println(theQueue.toString());

// serialize the Queue


System.out.println("serializing theQueue");
try {
FileOutputStream fout = new FileOutputStream("thequeue.dat");
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(theQueue);
oos.close();
}
catch (Exception e) { e.printStackTrace(); }
}

To unserialize (to load a previously saved Queue) :

public static void main(String args[]) {


Queue theQueue;

theQueue = new Queue();

// unserialize the Queue


System.out.println("unserializing theQueue");
try {
FileInputStream fin = new FileInputStream("thequeue.dat");
ObjectInputStream ois = new ObjectInputStream(fin);
theQueue = (Queue) ois.readObject();
ois.close();
}
catch (Exception e) { e.printStackTrace(); }

System.out.println(theQueue.toString());
}

Serialize an object to a file 331


Real's HowTo PDF version

Redirect stdout to a file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0061.html

[JDK1.1] application only

System.setOut(
new PrintStream(
new BufferedOutputStream(
new FileOutputStream("OUTPUT.DAT"))));

You may want to look at this How-to to redirect exception output to a Frame.

Get the "last modified" date from a file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0068.html

Simply use the lastModified() method from a file object. but the return value is system dependent and
should only be used to compare with other values returned by last modified. It should not be interpreted as
an absolute time.

String s1 = "file1.dat";
String s2 = "file2.dat";

File f1 = new File(s1);


File f2 = new File(s2);

if (f1.lastModified() < f2.lastModified())


System.out.println((s1 + " IS OLDER THAN " + S2);

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("yyyy-MM-dd").format(new Date(lastmodified));

Get the file creation time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-get-file-creation-time.html

Java.io.File returns the last modified time. To get the creation time, you need to use java.nio.Paths class.

Redirect stdout to a file 332


Real's HowTo PDF version

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.text.SimpleDateFormat;

public class FileCreationTime {

public static FileTime getCreationTime(File file) throws IOException {


Path p = Paths.get(file.getAbsolutePath());
BasicFileAttributes view
= Files.getFileAttributeView(p, BasicFileAttributeView.class)
.readAttributes();
FileTime fileTime=view.creationTime();
// also available view.lastAccessTine and view.lastModifiedTime
return fileTime;
}

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


File file = new File("c:/temp/images.jpg");
System.out.println(file + " creation time :"
+ new SimpleDateFormat("dd/MM/yyyy HH:mm:ss")
.format(FileCreationTime.getCreationTime(file).toMillis()));
}
}

Check if a file exists


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0070.html

import java.io.*;

public class FileTest {


public static void main(String args[]) {
File f = new File(args[0]);
System.out.println
(f + (f.exists()? " is found " : " is missing "));
}
}

Detect file (or folder) modification


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0490.html

Get the file creation time 333


Real's HowTo PDF version

For a single file, a thread is launched to check the lastModified value and compare it with the previous
value.

import java.util.*;
import java.io.*;

public abstract class FileWatcher extends TimerTask {


private long timeStamp;
private File file;

public FileWatcher( File file ) {


this.file = file;
this.timeStamp = file.lastModified();
}

public final void run() {


long timeStamp = file.lastModified();

if( this.timeStamp != timeStamp ) {


this.timeStamp = timeStamp;
onChange(file);
}
}

protected abstract void onChange( File file );


}

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

Detect file (or folder) modification 334


Real's HowTo PDF version

import java.io.*;

public abstract class DirWatcher extends TimerTask {


private String path;
private File filesArray [];
private HashMap dir = new HashMap();
private DirFilterWatcher dfw;

public DirWatcher(String path) {


this(path, "");
}

public DirWatcher(String path, String filter) {


this.path = path;
dfw = new DirFilterWatcher(filter);
filesArray = new File(path).listFiles(dfw);

// transfer to the hashmap be used a reference and keep the


// lastModfied value
for(int i = 0; i < filesArray.length; i++) {
dir.put(filesArray[i], new Long(filesArray[i].lastModified()));
}
}

public final void run() {


HashSet checkedFiles = new HashSet();
filesArray = new File(path).listFiles(dfw);

// scan the files and check for modification/addition


for(int i = 0; i < filesArray.length; i++) {
Long current = (Long)dir.get(filesArray[i]);
checkedFiles.add(filesArray[i]);
if (current == null) {
// new file
dir.put(filesArray[i], new Long(filesArray[i].lastModified()));
onChange(filesArray[i], "add");
}
else if (current.longValue() != filesArray[i].lastModified()){
// 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");
}
}

Detect file (or folder) modification 335


Real's HowTo PDF version

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[]) {
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 and this one too.

Detect file (or folder) modification 336


Real's HowTo PDF version

File/directory polling to detect change


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0617.html

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.

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

Java Native Access (JNA)

https://github.com/twall/jna#readme

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

Call native methods in a DLL from Java (NativeCall)

http://johannburkard.de/blog/programming/java/Call-native-methods-in-a-DLL-from-Java-without-JNI.html

In this blog entry, the package NativeCall is used to call the Windows API to get notification about
modification in given folder.

Java 7

Java 7 provides a mechanism to get notification on file change without polling (WatchService).

See this HowTo

File/directory polling to detect change 337


Real's HowTo PDF version

The simple (and naive!) approach

Detect file modification

Using Threads and file lookup at regular interval.

Detect file (or folder) modification (Java 7)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-detect-file-modification-event.html

Java 7 provides a mechanism to get notification on file change without polling (WatchService).

In this example, we set up a thread to watch CREATE event in a given folder. DELETE and MODIFY can
also be watched.

import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.List;

public class WatchThread extends Thread {

Path myDir;
WatchService watcher;

WatchThread(String path) {
try {
myDir = Paths.get(path);
watcher = myDir.getFileSystem().newWatchService();
myDir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE);
}
catch (Exception e) {
e.printStackTrace();
}
}

public void run() {


while (true) {
try {
WatchKey watchKey = watcher.take();
List<WatchEvent<?>> events = watchKey.pollEvents();
for (WatchEvent<?> event : events) {
// You can listen for these events too :

File/directory polling to detect change 338


Real's HowTo PDF version

// StandardWatchEventKinds.ENTRY_DELETE
// StandardWatchEventKinds.ENTRY_MODIFY
if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) {
System.out.println("Created: " + event.context().toString());
}
}
watchKey.reset();
}
catch (Exception e) {
System.out.println("Error: " + e.toString());
}
}
}
}

To use it :

public class WatchDemo {


public static void main (String args []) {
new WatchThread("C:/temp").start();
System.out.println("WatchThread is running!");
}
}

See also : this related howto and this one too.

Get the current directory


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0076.html

import java.io.File;
public class CurrentDir {
public static void main (String args[]) {
File dir1 = new File (".");
File dir2 = new File ("..");
try {
System.out.println ("Current dir : " + dir1.getCanonicalPath());
System.out.println ("Parent dir : " + dir2.getCanonicalPath());
}
catch(Exception e) {
e.printStackTrace();
}
}
}

Detect file (or folder) modification (Java 7) 339


Real's HowTo PDF version

Get the "root" of an application


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0581.html

By root, we mean the starting directory.

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

public class DummyApp {


public static void main(String args[]) throws Exception{
DummyApp s = new DummyApp();
s.getRoot();
}

public void getRoot() throws IOException, URISyntaxException{


URL u = getClass().getProtectionDomain().getCodeSource().getLocation();
File f = new File(u.toURI());
System.out.println(f.getParent());
}
}

Running from a regular class

C:\Applications\dev\HowTo>java -cp . DummyApp


C:\Applications\dev

Running from a jar

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

Get the content of a directory with a Filter


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0055.html

First you create a class that implements java.io.FilenameFilter and then code the accept() method. You call

Get the "root" of an application 340


Real's HowTo PDF version

File.list() with the filter as a parameter. The returned array of strings has all the names that passed through
the accept()filter.

import java.io.File;
import java.io.FilenameFilter;

public class Filter implements FilenameFilter {


protected String pattern;
public Filter (String str) {
pattern = str;
}

public boolean accept (File dir, String name) {


return name.toLowerCase().endsWith(pattern.toLowerCase());
}

public static void main (String args[]) {


if (args.length != 1) {
System.err.println
("usage: java Filter <pattern list> ex. java Filter java");
return;
}

Filter nf = new Filter (args[0]);


// current directory
File dir = new File (".");
String[] strs = dir.list(nf);
for (int i = 0; i < strs.length; i++) {
System.out.println (strs[i]);
}
}
}

Here a version to support multiple filters.

import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.Iterator;
import 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>
*/

Get the content of a directory with a Filter 341


Real's HowTo PDF version

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

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

Get the content of a directory with a Filter 342


Real's HowTo PDF version

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 onle-liner.

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 {

File [] foldersToBeChecked =
new File("J:\\").listFiles
(new FileFilter() {
public boolean accept(File pathname) {
return (pathname.isDirectory());
}
}
);
for(File f : foldersToBeChecked) {
System.out.println(f);
}
}
}

Get the content of a directory with subdirectories


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0056.html

import java.io.*;
import java.util.*;
public class DirUtils {

public static List recurseDir(String dir) {


String result, _result[];

result = recurseInDirFrom(dir);

Get the content of a directory with subdirectories 343


Real's HowTo PDF version

_result = result.split("\\|");
return Arrays.asList(_result);
}

private static String recurseInDirFrom(String dirItem) {


File file;
String list[], result;

result = dirItem;

file = new File(dirItem);


if (file.isDirectory()) {
list = file.list();
for (int i = 0; i < list.length; i++)
result = result + "|"
+ recurseInDirFrom(dirItem + File.separatorChar + list[i]);
}
return result;
}

public static void main(String arg[]) {


if (arg.length > 0) {
System.out.println("recursive Dirs from " + arg[0]);
System.out.println(DirUtils.recurseDir(arg[0]));
}
else {
System.out.println("Usage :");
System.out.println(" java DirUtils c:\temp");
}

/*
output:

C:\Applications>java DirUtils c:\zip


recursive Dir from c:\zip
[c:\zip, c:\zip\AutoIt.exe, c:\zip\cc32d48.exe, c:\zip\CODE_UPLOAD
148812122001.zip, c:\zip\groups2.txt, c:\zip\httrack-3.23.exe, c:\
zip\mass20.zip, c:\zip\mp3,c:\zip\mp3\BonkEnc-1.0-beta1.exe, c:\zi
p\mp3\cdex_150b10_enu.exe, c:\zip\mp3\hh_install.exe, c:\zip\mp3\T
PlayerSetup.exe, c:\zip\mp3\Tunchy1017full.zip, c:\zip\mp3\TWMP3en
coder.exe, c:\zip\ok, c:\zip\ok\CmdHerePowertoySetup.exe, c:\zip\o
k\htmldoc-1.8.23-winfree.exe, c:\zip\ok\j2sdk-1_4_1_02-windows-i58
6.exe, c:\zip\ok\jdk141-hh.zip, c:\zip\ok\jsref13.zip, c:\zip\ok\T
weakUiPowertoySetup.exe, c:\zip\quickmail-2_1.zip, c:\zip\RealOneP
layerV2GOLD.exe, c:\zip\RESTorefile2514.EXE,c:\zip\Shockwave_Insta
ller_Full.exe, c:\zip\Water.exe, c:\zip\winamp50_full.exe,c:\zip\w
olf, c:\zip\wolf\ok, c:\zip\wolf\ok\kf_box.zip, c:\zip\wolf\sp_off
lag_levels_1-4_final.zip, c:\zip\xpAntiSpy.zip]
*/
}
}

Get the content of a directory with subdirectories 344


Real's HowTo PDF version

Get directory content faster with many files


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-get-directory-content-faster-with-many-files.html

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 java.io.File;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystems;
import java.nio.file.Files;
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();

Get directory content faster with many files 345


Real's HowTo PDF version

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

Get directory content faster with many files 346


Real's HowTo PDF version

Make a directory
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0057.html

For application only, not Applet!

File td = new File("NewDirName");


td.mkdir();

Create a fixed-length file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0461.html

//
// usage : java CreateAFile 2048 twokbytes.dat
//
import java.io.FileOutputStream;
import java.io.IOException;

public class CreateAFile {


public static void main(String[] args) throws IOException {
byte[] buf = new byte[8192];
long n = Long.parseLong(args[0]);
FileOutputStream fos = new FileOutputStream(args[1]);
long m = n / buf.length;
for (long i = 0; i < m; i++) {
fos.write(buf, 0, buf.length);
}
fos.write(buf, 0, (int)(n % buf.length));
fos.close();
}
}

Delete a non-empty directory


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0483.html

Use the following recursive method.

import java.io.File;

Make a directory 347


Real's HowTo PDF version

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

Create a temporary file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0484.html

import java.io.File;

...

File temp = File.createTempFile("real",".howto");


temp.deleteOnExit();

Creates an empty file in the default temporary-file directory, using the given prefix ("real") and suffix
(".howto"). Plus, the temporary file will be deleted when the virtual machine terminates. Deletion will be
attempted only for normal termination of the virtual machine.

(Javadoc) The prefix argument must be at least three characters long. It is recommended that the prefix be a short, meaningful string such as "hjb" or
"mail". The suffix argument may be null, in which case the suffix ".tmp" will be used. To create the new file, the prefix and the suffix may first be adjusted
to fit the limitations of the underlying platform.

If the prefix is too long then it will be truncated, but its first three characters will always be preserved. If the
suffix is too long then it too will be truncated, but if it begins with a period character ('.') then the period
and the first three characters following it will always be preserved.

Once these adjustments have been made the name of the new file will be generated by concatenating the
prefix, five or more internally-generated characters, and the suffix.

Delete a non-empty directory 348


Real's HowTo PDF version

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 --> C:\TEMP\


Win XP --> C:\TEMP
Solaris --> /var/tmp/
Linux --> /var/tmp

It's not a bad idea to check if there is a trailing slash or not.

String tempdir = System.getProperty("java.io.tmpdir");

if ( !(tempdir.endsWith("/") || tempdir.endsWith("\\")) )
tempdir = tempdir + System.getProperty("file.separator");

Get the default character set of the JVM


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0505.html

public class Hello {


public static void main(String args[]) throws Exception{
// not crossplateform safe
System.out.println(System.getProperty("file.encoding"));
// jdk1.4
System.out.println(
new java.io.OutputStreamWriter(
new java.io.ByteArrayOutputStream()).getEncoding()
);
// jdk1.5
System.out.println(java.nio.charset.Charset.defaultCharset().name());
}
}

Output example (winXP)

>java Hello
Cp1252
Cp1252
windows-1252

Create a temporary file 349


Real's HowTo PDF version

See also java encoding table for the encoding sets supported.

Parse a pathname
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0514.html

import java.io.File;

public class ParsePathname {

public ParsePathname() { }

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


File f = new File
("c:/program files/adobe/Acrobat 5.0/Reader/acrord32.exe");
System.out.println("dir : " + f.getParent());
System.out.println("file : " + f.getName());
System.out.println("ext : " + getFileExtension(f.getName()));
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;
}
}

Handle CSV files


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0591.html

Get the default character set of the JVM 350


Real's HowTo PDF version

com.Ostermiller.util CSV Utils

CSVPrinter/CSVParser/ExcelCSVPrinter/ExcelCSVParser
http://ostermiller.org/utils/CSV.html

opencsv

A simple csv parser library for Java


http://opencsv.sourceforge.net/

ServingXML

Framework for flat/XML data transformations. Supported transformations : flat-XML, XML-flat, flat-flat,
and XML-XML
http://servingxml.sourceforge.net/

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/

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

CSVFile

A simple set of Java classes used to handle CSV


http://sourceforge.net/projects/csvfile

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/

CSVJDBC

CsvJdbc is a simple read-only JDBC driver that uses Comma Separated Value (CSV) files as database
tables.
http://csvjdbc.sourceforge.net/

Handle CSV files 351


Real's HowTo PDF version

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 multi-line formats and files containing lines have different
known formats ("mixed format" files).
http://jffp.sourceforge.net/

XSLT

XSLT is built-in in the JDK, you need to create your own transformation in a XSL file. Transform XML
into CSV using XSLT

Convert OEM (DOS) file to Ansi (Windows)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0524.html

We are using an InputStreamReader which convert the specified input encoding to Unicode and an
OutputStreamWriter which from Unicode to the specified output encoding.

This can be useful when migrating data from a legacy database (ex. Clipper, dBase) to newer DBMS (ex.
mySQL, Sybase).

import java.io.*;

public class OemToAnsi {

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


if (args.length != 2) {
System.out.println(
"Usage : java OemToAnsi inputdosfile outputansifile"
);
System.out.println(
" note : codepage input Cp850 codepage output Cp1252"
);
System.exit(1);
}
// input
FileInputStream fis = new FileInputStream(args[0]);
BufferedReader r =
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);

Handle CSV files 352


Real's HowTo PDF version

w.flush();
}
w.close();
r.close();
System.exit(0);
}
}

See also this related HowTo

Close a stream in a try/catch block


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0539.html

You close them in the finally clause using a special method.

public static boolean compareFile(File file1, File file2) {


BufferedInputStream in1 = null;
BufferedInputStream in2 = null;

try {
in1 = new BufferedInputStream(new FileInputStream(file1));
in2 = new BufferedInputStream(new FileInputStream(file2));

boolean result = true;


int i;
do {
i = in1.read();
result = (i == in2.read());
} while ( result && i != -1 );

return result;
}
catch (FileNotFoundException ex) {
ex.printStackTrace();
}
catch (IOException ex) {
ex.printStackTrace();
}
finally {
close(in1);
close(in2);
}

return false;
}

private static void close( InputStream is ) {


if ( is != null ) {
try {

Convert OEM (DOS) file to Ansi (Windows) 353


Real's HowTo PDF version

is.close();
}
catch ( IOException ioe ) {
ioe.printStackTrace();
}
}
}

Rename a file extension


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0541.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 end-of-line anchor so if the extracted extension occurs more than once in
the filename then all occurrences will be changed.

Close a stream in a try/catch block 354


Real's HowTo PDF version

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

Rename a file extension 355


Real's HowTo PDF version

To simply remove an extension, see this HowTo

Remove a file extension


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

Remove HTML tags from a file to extract only the TEXT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0424.html

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("java-new.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);
}

Remove a file extension 356


Real's HowTo PDF version

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.

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 java.io.IOException;
import java.io.FileReader;
import java.io.Reader;
import java.util.List;
import java.util.ArrayList;

import javax.swing.text.html.parser.ParserDelegator;
import javax.swing.text.html.HTMLEditorKit.ParserCallback;
import javax.swing.text.html.HTML.Tag;
import 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("java-new.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 well-formed.

Remove HTML tags from a file to extract only the TEXT 357
Real's HowTo PDF version

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;
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/java-language.html");
System.out.println(HTMLUtils.extractText(reader));
}
}

Using Apache Tika

Apache Tika

import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.BodyContentHandler;
import org.xml.sax.ContentHandler;

public class ParseHTMLWithTika {


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

Remove HTML tags from a file to extract only the TEXT 358
Real's HowTo PDF version

InputStream is = null;
try {

is = new FileInputStream("C:/Temp/java-x.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

Get the Mime Type from a File


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0487.html

Using Java 7

Files.html#probeContentType

import java.io.IOException;
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");
System.out.println(Files.probeContentType(source));
// output : image/tiff
}
}

The default implementation is OS-specific and not very complete. It's possible to register a better detector,
like for example Apache Tika, see Transparently improve Java 7 mime-type recognition with Apache Tika.

Get the Mime Type from a File 359


Real's HowTo PDF version

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

The built-in mime-type list is very limited but a mechanism is available to add very easily more Mime
Types/extensions.

The MimetypesFileTypeMap looks in various places in the user's system for MIME types file entries.
When requests are made to search for MIME types in the MimetypesFileTypeMap, it searches MIME types
files in the following order:

1. Programmatically added entries to the MimetypesFileTypeMap instance.


2. The file .mime.types in the user's home directory.
3. The file <java.home>/lib/mime.types.
4. The file or resources named META-INF/mime.types.
5. The file or resource named META-INF/mimetypes.default (usually found only in the activation.jar
file).

This method is interesting when you need to deal with incoming files with the filenames normalized. The
result is very fast because only the extension is used to guess the nature of a given file.

Using java.net.URL

Warning : this method is very slow!.

Like the above method a match is done with the extension. The mapping between the extension and the
mime-type is defined in the file [jre_home]\lib\content-types.properties

import java.net.*;

public class FileUtils{

Get the Mime Type from a File 360


Real's HowTo PDF version

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 {

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

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 up-to-date regarding the filetypes supported, Office 2007 formats are supported
(docs/pptx/xlsx/etc...).

Get the Mime Type from a File 361


Real's HowTo PDF version

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 org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.BodyContentHandler;
import 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();
}
finally {
if (is != null) is.close();
}
}
}

You can download here a ZIP containing the required jars if you want to check it out.

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

Get the Mime Type from a File 362


Real's HowTo PDF version

// 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 Jean-Marc Autexier and sygsix for the tip!

Using mime-util

Another tool is mime-util. 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 mime-util is that it is very lightweight. Only 1 dependency with slf4j

Using Droid

DROID (Digital Record Object Identification) is a software tool to perform automated batch identification
of file formats.

DROID uses internal and external signatures to identify and report the specific file format versions of
digital files. These signatures are stored in an XML signature file, generated from information recorded in
the PRONOM technical registry. New and updated signatures are regularly added to PRONOM, and
DROID can be configured to automatically download updated signature files from the PRONOM website
via web services.

It can be invoked from two interfaces, a Java Swing GUI or a command line interface.

http://droid.sourceforge.net/wiki/index.php/Introduction

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:

Get the Mime Type from a File 363


Real's HowTo PDF version

• Crawling of information sources: file systems, websites, mail boxes


• MIME type identification
• Full-text and metadata extraction of various file formats
• Opening of crawled resources

For each of these parts, a set of APIs has been developed and a number of implementations is provided.

http://aperture.wiki.sourceforge.net/Overview

Sort a directory listing (based on the last modified timestamp)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0606.html

This HowTo sorts a directory listing in ascending or descending order (based on the last modified
timestamp).

import java.io.*;
import java.util.Arrays;
import java.util.Comparator;
import 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()));
}

@SuppressWarnings("unchecked")
public static File[] dirListByAscendingDate(File folder) {
if (!folder.isDirectory()) {
return null;
}
File files[] = folder.listFiles();
Arrays.sort( files, new Comparator()
{

Sort a directory listing (based on the last modified timestamp) 364


Real's HowTo PDF version

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.

Sort files by the extension


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0641.html

import java.io.*;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Comparator;

public class FileUtils{

/**
* returns a folder content sorted by extension
* case-insensitive ,ascending order
* subfolders are not included
* @param folder folder name
* @return
* @throws IOException if not a folder or not found
*/

Sort files by the extension 365


Real's HowTo PDF version

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

Sort files by the extension 366


Real's HowTo PDF version

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

Filter a directory listing by date


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0607.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("yyyy-MM-dd");
}

public boolean accept(File dir, String name) {


Date d = new Date(new File(dir, name).lastModified());
String current = sdf.format(d);

Filter a directory listing by date 367


Real's HowTo PDF version

return ((dateStart.compareTo(current) < 0


&& (dateEnd.compareTo(current) >= 0)));
}
}

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("yyyy-MM-dd");
FileFilterDateIntervalUtils filter =
new FileFilterDateIntervalUtils("2004-01-01", "2004-12-31");
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.

Convert wildcard to a regex expression


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

Convert wildcard to a regex expression 368


Real's HowTo PDF version

System.out.println(Pattern.matches(wildcardToRegex("ABC*"), test));
/*
output :
123ABC
true
true
false
true
false
true
false
true
false
false
*/

public static String wildcardToRegex(String wildcard){


StringBuffer s = new StringBuffer(wildcard.length());
s.append('^');
for (int i = 0, is = wildcard.length(); i < is; i++) {
char c = wildcard.charAt(i);
switch(c) {
case '*':
s.append(".*");
break;
case '?':
s.append(".");
break;
// escape special regexp-characters
case '(': case ')': case '[': case ']': case '$':
case '^': case '.': case '{': case '}': case '|':
case '\\':
s.append("\\");
s.append(c);
break;
default:
s.append(c);
break;
}
}
s.append('$');
return(s.toString());
}
}

Shorten a long path


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0661.html

Shorten a long path 369


Real's HowTo PDF version

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 static final int DEFAULT_SHORTENER_THRESHOLD = 4;


public static final String SHORTENER_BACKSLASH_REGEX = "\\\\";
public static final String SHORTENER_SLASH_REGEX = "/";
public static final String SHORTENER_BACKSLASH = "\\";
public static final String SHORTENER_SLASH = "/";
public static final String SHORTENER_ELLIPSE = "...";

private FileUtils() { }

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;

Shorten a long path 370


Real's HowTo PDF version

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

if (index == (elem - 1)) {


sb.append(pathtemp[elem - 1]);
}
else {
sb.append(SHORTENER_ELLIPSE)
.append(sep)

Shorten a long path 371


Real's HowTo PDF version

.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

Shorten a long path 372


Real's HowTo PDF version

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

Shorten a long path 373


Real's HowTo PDF version

*/
}
}

See also this HowTo : Ellipse a String.

Force a valid Windows filename


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

Related HowTo : Check if filename is valid

Check if filename is valid


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-check-if-a-filename-is-valid.html

This HowTo will only check if a given filename is valid according to the OS rules.

Force a valid Windows filename 374


Real's HowTo PDF version

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.

Dump a file to a HEX file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0667.html

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.PrintStream;

public class FileUtils {

public static void hexDump(PrintStream out, File file) throws IOException {

Check if filename is valid 375


Real's HowTo PDF version

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 43 41 54 49 4F 4E 20 44 41 54 41 5C 4D 4F 5A 49 CATION DATA\MOZI
343F0 4C 4C 41 5C 50 52 4F 46 49 4C 45 53 5C 44 45 46 LLA\PROFILES\DEF
34400 41 55 4C 54 5C 43 42 50 4D 53 35 4E 38 2E 53 4C AULT\CBPMS5N8.SL
34410 54 5C 4D 41 49 4C 5C 4D 41 49 4C 5C 54 52 41 53 T\MAIL\MAIL\TRAS
34420 48 0D 0A 20 20 20 20 20 20 54 68 69 73 20 66 69 H.. This fi
34430 6C 65 20 69 73 20 61 20 6D 61 69 6C 62 6F 78 2E le is a mailbox.
34440 20 54 6F 20 61 76 6F 69 64 20 69 6D 70 61 63 74 To avoid impact
...

Dump a file to a HEX file 376


Real's HowTo PDF version

List all files in the classpath or in a Jar


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0665.html

List the files found in the classpath, the bootclasspath, the extension directory and in a Jar.

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import 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);
}
}
}

/**
* List the content of the given jar

List all files in the classpath or in a Jar 377


Real's HowTo PDF version

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

}
}

Handle UTF8 file with BOM


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-handle-utf8-file-with-bom.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 byte-order indicator, the BOM character may also
indicate which of the several Unicode representations the text is encoded in.

Handle UTF8 file with BOM 378


Real's HowTo PDF version

The common BOMs are :

Encoding Representation (hexadecimal) Representation (decimal)


UTF-8 EF BB BF 239 187 191
UTF-16 (BE) FE FF 254 255
UTF-16 (LE) FF FE 255 254
UTF-32 (BE) 00 00 FE FF 0 0 254 255
UTF-32 (LE) FF FE 00 00 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 UTF-8.

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

Handle UTF8 file with BOM 379


Real's HowTo PDF version

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.

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

Handle UTF8 file with BOM 380


Real's HowTo PDF version

if (s.startsWith(UTF8_BOM)) {
s = s.substring(1);
}
return s;
}
}

Touch a file
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-touch-a-file.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/java-x.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

Touch a file 381


Real's HowTo PDF version

Handle Excel files


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0516.html

There are many solutions to read or write Excel spreadsheets from Java. This HowTo is only about
OpenSource (and free) solutions.

JDBC-ODBC Excel driver

For Java 8 you cannot use the JDBC-ODBC Bridge because it has been removed.
This solution lets you access your Excel worksheet with SQL SELECT statement. The required ODBC
driver is included in a regular Windows installation and the JDBC-ODBC bridge is used to access the Excel
DSN.

See this HowTo for an example.

JExcel

Java Excel API is a java API enabling developers to read, write, and modify Excel spreadsheets
dynamically. Any operating system which can run a Java virtual machine can both process and deliver
Excel spreadsheets. One nice thing about JExcelApi is that it has no dependencies on any third party
libraries.

Example : output an Excel file from a Servlet

import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

public class Sample extends HttpServlet {


public void doGet
(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
OutputStream out = null;
try {
response.setContentType("application/vnd.ms-excel");
response.setHeader
("Content-Disposition", "attachment; filename=sampleName.xls");

Handle Excel files 382


Real's HowTo PDF version

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/

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/

Handle Excel files 383


Real's HowTo PDF version

JXLS

jXLS is a project that allows creation of extremely complex Excel reports just in several lines of code. It is
based on Jakarta POI.

With jXLS, all you need is to create XLS template file with all required formatting, formulas etc using
specific notation to indicate placement of data and then write a couple lines of code to invoke jXLS engine
passing XLS template and the exported data as parameters.

Example :
The XLS Template

Employees
Name Age Payment Bonus
${employee.name} ${employee.age} ${employee.payment} ${employee.bonus}
$[SUM(@employee.payment@)]

with the code

Collection staff = new HashSet();


staff.add(new Employee("Derek", 35, 3000, 0.30));
staff.add(new Employee("Elsa", 28, 1500, 0.15));
Map beans = new HashMap();
beans.put("employee", staff);
XLSTransformer transformer = new XLSTransformer();
transformer.transformXLS(templateFileName, beans, destFileName);

gives the result

Employees
Name Age Payment Bonus
Derek 35 3000 30,00%
Else 28 1500 15,00%
4500

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

Handle Excel files 384


Real's HowTo PDF version

String nopolicy = policy.getContents();


// do something : process(nopolicy);
}
}

See http://jxls.sourceforge.net/

xlSQL

xlSQL is a JDBC Driver for Excel and CSV data sources. Documents can be read and written with SQL as
if they were tables in a database.

You can export XLS to XML or SQL INSERT statements. xlSQL includes its own "zero-admin" mySQL
database. The documentation is minimal at this time.

See http://xlsql.sourceforge.net/

JCOM

JCOM is a Java to COM bridge library. With JCOM you can call a COM object from Java as if it were a
Java object without having to deal with the internals of JNI. The documentation is minimal (in Japanese!).

Example :

import jp.ne.so_net.ga2.no_ji.jcom.excel8.*;
import jp.ne.so_net.ga2.no_ji.jcom.*;
import java.io.File;
import java.util.Date;

class TestExcel {
public static void main(String[] args) throws Exception {
ReleaseManager rm = new ReleaseManager();
try {
System.out.println("EXCEL startup...");
// if already started, open new window
ExcelApplication excel = new ExcelApplication(rm);
excel.Visible(true);
// display any information
System.out.println("Version="+excel.Version());
System.out.println("UserName="+excel.UserName());
System.out.println("Caption="+excel.Caption());
System.out.println("Value="+excel.Value());

ExcelWorkbooks xlBooks = excel.Workbooks();


ExcelWorkbook xlBook = xlBooks.Add(); // create new book

// enumurate all files


System.out.println
("set infomation of files in current directory to cell ...");
ExcelWorksheets xlSheets = xlBook.Worksheets();

Handle Excel files 385


Real's HowTo PDF version

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

System.out.println("thank you .");


}
catch(Exception e) { e.printStackTrace(); }
finally { rm.release(); }
}
}

See http://sourceforge.net/projects/jcom

Handle Excel files 386


Real's HowTo PDF version

See also this HowTo for an alternative package to access a COM package from Java.

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


giffy.setBounds(100, 100, 400, 200);

Handle Excel files 387


Real's HowTo PDF version

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.

Create an Excel file (the easy way)


Current version of this HowTo :

Create an Excel file (the easy way) 388


Real's HowTo PDF version

http://www.rgagnon.com/javadetails/../javadetails/java-0586.html

While you can use specialized packages to create native Excel file, an easy way to import data into Excel is
to create an HTML file and embed the date into a TABLE tag. You give to the file the XLS extension and
Excel will do the translation for you!

With a text editor or from a program, create a file named test.xls with this content

<TABLE>
<th><h4>Just testing</h4>
<TR><TD width="20">1</TD><TD width="30">2</TD><TD width="40">3</TD></TR>
<TR><TD>4</TD><TD>4</TD><TD>6</TD></TR>
<TR><TD>7</TD><TD>8</TD><TD>9</TD></TR>
<TR><TD>=SUM(A3:A5)</TD><TD>=SUM(B3:B5)</TD><TD>=SUM(C3:C5)</TD></TR>
</TABLE>

Now you can double click on the saved file to load it into Excel and the translation will be done.

This trick works with OpenOffice too.

From a server, remember to send the appropriate MIME TYPE : application/excel to the client.

See also this HowTo

Detect if a XLS Excel file contains a macro (using POI)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-detect-if-xls-excel-file-contains-a-macro.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;
}

public void processPOIFSReaderEvent(POIFSReaderEvent event) {

Detect if a XLS Excel file contains a macro (using POI) 389


Real's HowTo PDF version

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

Create or process PDF files


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0523.html

Create or process PDF files 390


Real's HowTo PDF version

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 com.lowagie.text.Element;
import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;

public class AddWatermarkPageNumbers {


public static void main(String[] args) {
System.out.println("Add watermarks and pagenumbers");
try {
PdfReader reader = new PdfReader("ChapterSection.pdf");
int n = reader.getNumberOfPages();
// create a stamper that will copy the document to a new file
PdfStamper stamp = new PdfStamper(reader,
new FileOutputStream("watermark_pagenumbers.pdf"));
// adding some metadata

Create or process PDF files 391


Real's HowTo PDF version

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

Create or process PDF files 392


Real's HowTo PDF version

iText - Create a PDF


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0618.html

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. itext-2.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 page-size 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]);

iText - Create a PDF 393


Real's HowTo PDF version

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

Split a PDF file (using iText)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0647.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 file-001.pdf ... file-nnn.pdf
*
* itext-2.1.5.jar
*/

import java.io.FileOutputStream;

import com.lowagie.text.Document;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfReader;

public class SplitPDFFile {

/**

Split a PDF file (using iText) 394


Real's HowTo PDF version

* @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\tx-001.pdf
Writing d:\temp\x\tx-002.pdf
Writing d:\temp\x\tx-003.pdf
*/

}
}

Concatenate PDF files (using iText)


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

Concatenate PDF files (using iText) 395


Real's HowTo PDF version

import java.util.ArrayList;
import java.util.List;

import com.lowagie.text.Document;
import com.lowagie.text.pdf.PRAcroForm;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfReader;
import 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;

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

Concatenate PDF files (using iText) 396


Real's HowTo PDF version

writer.copyAcroForm(reader);
}
f++;
}
if (!master.isEmpty()) {
writer.setOutlines(master);
}
document.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}

ref : iText example

See also this HowTo.

Convert TIF to PDF


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0645.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 letter-page dimension.

import java.io.FileOutputStream;

import com.lowagie.text.Document;
import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfWriter;
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++) {

Convert TIF to PDF 397


Real's HowTo PDF version

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

Convert TIF to PDF 398


Real's HowTo PDF version

Convert HTML to PDF using iText


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-html-to-pdf-using-itext.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 com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.html.simpleparser.HTMLWorker; // deprecated
import com.itextpdf.text.pdf.PdfWriter;

public class HtmlToPDF1 {


// itextpdf-5.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 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 [email protected]." +
"<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) {

Convert HTML to PDF using iText 399


Real's HowTo PDF version

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 com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;
public class HtmlToPDF2 {

// itextpdf-5.4.1.jar http://sourceforge.net/projects/itext/files/iText/
// xmlworker-5.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 [email protected].</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='background-color: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.");

Convert HTML to PDF using iText 400


Real's HowTo PDF version

}
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

Convert HTML to PDF using YAHP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-convert-html-to-pdf-using-yahp.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 java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import 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();

Convert HTML to PDF using YAHP 401


Real's HowTo PDF version

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 java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import 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 utf-8
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,

Convert HTML to PDF using YAHP 402


Real's HowTo PDF version

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.

Convert PNG/JPG/GIF to PDF using iText


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-image-to-pdf-using-itext.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();
}
}
}

Convert PNG/JPG/GIF to PDF using iText 403


Real's HowTo PDF version

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

Print a PDF
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-print-a-pdf.html

[Windows only]
You can launch the Acrobat Reader to print a PDF to the default printer.

More infos the "unsupported" command-line 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");
}
}

Print a PDF 404


Real's HowTo PDF version

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

Extract text from a PDF using Apache Tika


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-extract-text-from-a-pdf.html

You can do it with Apache Tika

import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.tika.parser.pdf.PDFParser;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.sax.BodyContentHandler;
import org.xml.sax.ContentHandler;

public class ParsePDFWithTika {


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

InputStream is = null;
try {
is = new FileInputStream("C:/Temp/realhowto-vbs-20121221.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.

Create a compressed (ZIP) file

Extract text from a PDF using Apache Tika 405


Real's HowTo PDF version

Current version of this HowTo :


http://www.rgagnon.com/javadetails/../javadetails/java-0065.html

/*
** a simple ZIP tool
**
** ex. java Zip file.1 file.2 > file.zip
**
*/
import java.io.*;
import java.util.zip.*;

class Zip {
public static void main(String args[]) throws IOException {
byte b[] = new byte[512];
ZipOutputStream zout = new ZipOutputStream(System.out);
for(int i = 0; i < args.length; i ++) {
InputStream in = new FileInputStream(args[i]);
ZipEntry e = new ZipEntry(args[i].replace(File.separatorChar,'/'));
zout.putNextEntry(e);
int len=0;
while((len=in.read(b)) != -1) {
zout.write(b,0,len);
}
zout.closeEntry();
print(e);
}
zout.close();
}

public static void print(ZipEntry e){


PrintStream err = System.err;
err.print("added " + e.getName());
if (e.getMethod() == ZipEntry.DEFLATED) {
long size = e.getSize();
if (size > 0) {
long csize = e.getCompressedSize();
long ratio = ((size-csize)*100) / size;
err.println(" (deflated " + ratio + "%)");
}
else {
err.println(" (deflated 0%)");
}
}
else {
err.println(" (stored 0%)");
}
}
}

Create a compressed (ZIP) file 406


Real's HowTo PDF version

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.

Display compressed (ZIP) file content


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0066.html

/*
** a simple viewZIP tool
**
** ex. java ViewZip file.zip
**
*/
import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.text.*;

class ViewZip {
public static void main(String args[]) throws IOException {
InputStream in = new BufferedInputStream(new FileInputStream(args[0]));
ZipInputStream zin = new ZipInputStream(in);
ZipEntry e;
System.err.println("Size\t Date Time Method Ratio Name");
System.err.println("----\t ---- ---- ------ ----- ----");
while((e=zin.getNextEntry())!= null) {
zin.closeEntry();
print(e);
}
zin.close();
}

public static void print(ZipEntry e) {


PrintStream err = System.err;
err.print(e.getSize() + "\t");

DateFormat df = new SimpleDateFormat ("yyyy.mm.dd hh:mm:ss");


Date d = new Date(e.getTime());

err.print(df.format(d) + " ");


if (e.getMethod() == ZipEntry.DEFLATED) {
err.print("deflated ");
long size = e.getSize();
if (size > 0) {
long csize = e.getCompressedSize();
long ratio = ((size-csize)*100) / size;
if (ratio < 10) {
err.write(' ');
}
err.print(ratio + "% ");

Display compressed (ZIP) file content 407


Real's HowTo PDF version

}
else {
err.print(" 0% ");
}
}
else {
err.println(" (stored 0 %");
}

err.println(e.getName());
}
}

Expand the compressed (ZIP) file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0067.html

/*
** a simple unZIP tool
**
** ex. java UnZip file.zip file1 to unzip file 1 from file.zip
** java UnZip file.zip to unzip file.zip
**
*/
import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.text.*;

class UnZip {
public static void main(String args[]) throws IOException {
InputStream in =
new BufferedInputStream(new FileInputStream(args[0]));
ZipInputStream zin = new ZipInputStream(in);
ZipEntry e;

while((e=zin.getNextEntry())!= null) {
if (args.length > 1) {
if (e.getName().equals(args[1])) {
unzip(zin, args[1]);
break;
}
}
unzip(zin, e.getName());
}
zin.close();
}

public static void unzip(ZipInputStream zin, String s)

Expand the compressed (ZIP) file 408


Real's HowTo PDF version

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

Emit a beep
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0001.html

There are three ways to emit a beep in Java.


• Use an AU audio file
For Java, AU files need to be created at a sample rate of 8000. Any sample rate beyound that will not work. See also this How-to.

• 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.

Emit a tone
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0499.html

Emit a beep 409


Real's HowTo PDF version

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

}
}

Emit a tone 410


Real's HowTo PDF version

See also this HowTo

Play an audio file from an application


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0006.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 java.io.File;
import java.io.FileInputStream;
import javax.sound.sampled.*;
import javax.swing.*;

public class AppWithSound extends JFrame {

private static final long serialVersionUID = 1L;

public static void main(String[] args) {


SwingUtilities.invokeLater(new Runnable() {
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

Play an audio file from an application 411


Real's HowTo PDF version

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

Produce special sound effect


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

Produce special sound effect 412


Real's HowTo PDF version

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;

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

Produce special sound effect 413


Real's HowTo PDF version

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

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 javax.sound.sampled.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

Produce special sound effect 414


Real's HowTo PDF version

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 {

Produce special sound effect 415


Real's HowTo PDF version

AudioFormat af = new AudioFormat(8000f, // sampleRate


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

Use the Java Speech API (JSPAPI)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-use-java-speech-api.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 third-parties provide the implementations.

The most popular implementation is the open-source TTS (Text-To-Speech) package,


http://freetts.sourceforge.net/

You download the required jars here : http://sourceforge.net/projects/freetts/files/

The configuration is done in 2 steps.

Use the Java Speech API (JSPAPI) 416


Real's HowTo PDF version

• 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
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 javax.speech.AudioException;
import javax.speech.Central;
import javax.speech.EngineException;
import javax.speech.EngineStateError;
import javax.speech.synthesis.Synthesizer;
import javax.speech.synthesis.SynthesizerModeDesc;
import 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);
}

Use the Java Speech API (JSPAPI) 417


Real's HowTo PDF version

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

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.ryan-h.com/uncategorized/java-speech-jsapi-freetts/
• http://java.sun.com/products/java-media/speech/forDevelopers/jsapi-doc/javax/speech/package-summary.html
• http://today.java.net/pub/a/today/2006/04/13/vocal-java.html

Play a Windows sound


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-play-a-windows-sound.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);

Play a Windows sound 418


Real's HowTo PDF version

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 :
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 Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Play a Windows sound 419


JDBC
java-jdbc

Get JDBC driver for major database vendors


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0113.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 ODBC-JDBC bridge included
with the JDK, the performance and stability of this solution is not great (and it is not included any more
since JDK8).

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 platform-independent and does not require installing additional client or server
software to provide access to MDB files.

http://www.csv-jdbc.com/stels_mdb_jdbc.htm

Connect to a database via JDBC-ODBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0107.html

This HowTo is deprecated. For Java 8 you cannot use the JDBC-ODBC Bridge because it has been
removed.
You have to keep in mind that the bridge JDBC-ODBC is only useful in an Application, you can't use it
with JAVA Applet because ODBC requires some DLL on the client machine (forbidden for security
reason).
import java.net.URL;
import java.sql.*;

class JDBCapp {

JDBC 420
Real's HowTo PDF version

static Connection theConn;

public static void main (String args[]) {


try {
// connection to an ACCESS MDB
theConn = MyConnection.getConnection();

ResultSet rs;
Statement stmt;
String sql;

sql = "select objet from Email";


stmt = theConn.createStatement();
rs = stmt.executeQuery(sql);

while (rs.next()) {
System.out.println(rs.getString("objet"));
}
rs.close();
stmt.close();
}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
if (theConn != null) theConn.close();
}
catch (Exception e) {
}
}

}
}

class MyConnection {
public static Connection getConnection() throws Exception {
Driver d = (Driver)Class.forName
("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");

*/
}
}

Connect to a database via JDBC-ODBC 421


Real's HowTo PDF version

SELECT data from a table


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0108.html

Note:the MyConnection class was used to connect to the DB

With a Prepared Statement (only 1 row)

String id = cust_id.getText();
try {
PreparedStatement prepstmt;
boolean found = false;
prepstmt = theConn.prepareStatement
("select custName, CustAddr from tCust where custId = ?");
prepstmt.setString(1, id);

ResultSet rs;
rs = prepstmt.executeQuery();

found = rs.next();
if (found)
System.out.println(rs.getString(1));
else
System.out.println("Customer " + id + " not found!");
prepstmt.close();
}
catch (Exception e) {
e.printStackTrace();
}

With a Statement (many rows)

String name = cust_name.getText();


try {
Statement stmt;
String sql;

sql = "select custName from tCust where custName = "


+= "'" + name + "'";
stmt = theConn.createStatement();

ResultSet rs;
rs = stmt.executeQuery();

while (rs.next()) {
System.out.println(rs.getString("custName"));
}
rs.close();
stmt.close();

SELECT data from a table 422


Real's HowTo PDF version

}
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.

INSERT data into a table


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0109.html

Note:the MyConnection class was used to connect to the DB

Statement stmt;
String sql;
int rows;

sql = "INSERT INTO tCust "


+ "(custId, custName, custAddr) "
+ "VALUES "
+ "('" + custId + "',"
+ "('" + custName + "',"
+ "('" + custAddr + "')";

stmt = theConn.createStatement();
rows = stmt.executeUpdate(sql);
theConn.dbConn.commit();
stmt.close();

You need to be aware to the snippet above contains a SQL Injection vulnerability. String concatentation of this form can only be used if you first validate
the fields to include only alphanumeric characters. Even, then it is generally considered bad practice when prepared statements solve this problem more
cleanly. This is especially when you in a Web application environnement.

Thanks to Lawrence Angrave for the warning.

Before inserting data containing quotes, you may need to double them (so "Real's HowTo" -> "Real''s
HowTo"). You can use the following function to "prepare" your string.
public 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"));

INSERT data into a table 423


Real's HowTo PDF version

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

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('\\')");

INSERT data into a table 424


Real's HowTo PDF version

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('\\\\')");

MODIFY data in a table


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0110.html

Note:the MyConnection class was used to connect to the DB

PreparedStatement prepstmt;
try {
prepstmt = theConn.prepareStatement
("UPDATE tCust SET custName = ? "+
" WHERE custId = ?");
prepstmt.setString(1,"Smith");
prepstmt.setString(2, cust_id.getText());
prepstmt.executeUpdate();

theConn.commit();
prepstmt.close();
}
catch (Exception e) {
e.printStackTrace();
}

DELETE data in a table


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0111.html

Note:the MyConnection class was used to connect to the DB

PreparedStatement prepstmt;
try {
prepstmt = theConn.prepareStatement
("DELETE FROM tCust "+
" WHERE custId = ?");

prepstmt.setString(1,cust_id.getText());
prepstmt.executeUpdate();

theConn.commit();

MODIFY data in a table 425


Real's HowTo PDF version

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

Test for an empty ResultSet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0116.html

boolean found;
ResultSet rs;
...
// execute the query and then
found = rs.next();
if (found)
System.out.println("Record found");
else
System.out.println("RECORD NOT FOUND");

Get row count from SQL


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

DELETE data in a table 426


Real's HowTo PDF version

NOTE : Your JDBC driver may not support this feature.

Store and retrieve an object from a table


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0117.html

Assume that we have a table called "Employee", with only one field called "emp" and "long binary" or
"blob" as data type. We want to insert an instance of the class "Employee" into the table "Employee". The
object "Employee" will be serialized into the table "Employee" ( ideally the table "Employee" should have
an index key, something like emp_id, but for the example there is none).

import java.net.URL;
import java.sql.*;
import java.io.*;

class JDBCapp {
static MyConnection theConn;

public static void main (String args[]) {


JDBCapp j = new JDBCapp();
j.connectToDB();
j.insertIntoEmp();
j.selectFromEmp();
}

public void connectToDB() {


theConn = new MyConnection();
theConn.connect("your_db_profile", "username", "password");
}

public void insertIntoEmp() {


Employee employee = new Employee(42,"Real Gagnon", 98000);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(employee);
// serialize the employee object into a byte array
byte[] employeeAsBytes = baos.toByteArray();
PreparedStatement pstmt =
theConn.dbConn.prepareStatement
("INSERT INTO EMPLOYEE (emp) VALUES(?)");
ByteArrayInputStream bais =
new ByteArrayInputStream(employeeAsBytes);
// bind our byte array to the emp column
pstmt.setBinaryStream(1,bais, employeeAsBytes.length);
pstmt.executeUpdate();
theConn.dbConn.commit();

Get row count from SQL 427


Real's HowTo PDF version

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);
// re-create the object
Employee emp = (Employee)ois.readObject();
// display the result for demonstration
System.out.println(emp.name);
}
stmt.close();
rs.close();
}
catch(Exception e) {
e.printStackTrace();
}
}
}

class Employee implements Serializable {


int ID;
String name;
double salary;

public Employee(int ID, String name, double salary) {


this.ID = ID;
this.name = name;
this.salary = salary;
}
}

class MyConnection {
Connection dbConn = null;
void connect(String db, String user, String passw) {
try {

Store and retrieve an object from a table 428


Real's HowTo PDF version

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

Retrieve an Image
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0118.html

// column is column index in ResultSet containing the image,


// we assume that the type is LONGVARBINARY
Image myImage = null;
InputStream stream = rset.getBinaryStream(column);
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
int a1 = stream.read();
while (a1 >= 0) {
output.write((char)a1);
a1 = stream.read();
}
myImage =
Toolkit.getDefaultToolkit().createImage(output.toByteArray());
output.close();
}
catch(Exception e){}

Insert an Image
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0119.html

Retrieve an Image 429


Real's HowTo PDF version

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

Call a stored procedure


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0115.html

We assume that the Connection is known as :

Connection conn;

then

String query = "begin thePackage.theProcedure(?,?,?); end;";


CallableStatement cs = conn.prepareCall(query);
cs.setString(1, "string parameter"); // #1 is INPUT
cs.setInt(2, 1); // #2 is INPUT
cs.registerOutParameter(2, Types.INTEGER); // and OUTPUT
cs.registerOutParameter(3, Types.INTEGER); // #3 is OUTPUT
cs.execute();

int output_parm2 = cs.getInt(2); // get the result from OUTPUT #2


int output_parm3 = cs.getInt(3); // get the result from OUTPUT #3

Stored procedure with Input/Output parms and a ResultSet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0120.html

Thanks to T. Guirado for the tips.

public static int storedProcWithResultSet (String parms) throws Exception


// Stored procedure to be called.
CallableStatement cs = conn.prepareCall
("{? = call mypackage.p_astoreproc (?,?,?,?,?,?,?)}");

// register input parameters

Insert an Image 430


Real's HowTo PDF version

cs.setString(2, "");
cs.setString(3, "");
cs.setString(4, parms);
// regsiter ouput parameters
cs.registerOutParameter(5, java.sql.Types.CHAR);
cs.registerOutParameter(6, java.sql.Types.CHAR);
cs.registerOutParameter(7, java.sql.Types.CHAR);

// Procedure execution
ResultSet rs = cs.executeQuery();

// Note that you need to retrieve the ResultSet _before_ retrieving


// OUTPUT parameters.
if ( rs == null)
System.out.println( "No resultSet!");
else {
// To retrieve columns info.
ResultSetMetaData rsmd = rs.getMetaData();
int nbCol = rsmd.getColumnCount();

int i = 0;
int j = 1;

Vector vResSet = new Vector();


while (rs.next ()) {
System.out.println( "Record " + (i+1));
// putting the ResultSet columns in a vector
for ( j = 1; j <= nbCol ; j++){
vResSet.insertElementAt(rs.getString(j), 0);
vResSet.addElement(rs.getString(j));
}

// Reading vector to print ResultSet data


for ( int k = 0 ; k < nbColonnes ; k++ ) {
if ( vResSet.elementAt(k) != null)
System.out.println( vResSet.elementAt(k).toString());
else
System.out.println( "Column " + (k+1) + " Null");
}
i++;
}
}

// Retrieving Strored Procedure OUTPUT parameters


System.out.println( "return code of Stored procedure = : "
+ 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);
}

Stored procedure with Input/Output parms and a ResultSet 431


Real's HowTo PDF version

Fix incomplete field returned by the ResultSet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0121.html

Some JDBC driver have limit about how big returned records can be.

First use the getMaxRowSize() and doesMaxRowSizeIncludeBlobs() from the DatabaseMetaData class to
see what the maximum supported by the driver. Then getMaxFieldSize() and setMaxFieldSize() from the
Statement class to adjust if necessary the current maximum value.

Transfer a ResultSet to a JTable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0309.html

// TableModel definition
String[] tableColumnsName = {"col 1","col 2","col 3"};
DefaultTableModel aModel = (DefaultTableModel) aTable.getModel();
aModel.setColumnIdentifiers(tableColumnsName);

// the query
ResultSet rs =
statement.executeQuery("select col1,col2,col3 from mytable");

// Loop through the ResultSet and transfer in the Model


java.sql.ResultSetMetaData rsmd = rs.getMetaData();
int colNo = rsmd.getColumnCount();
while(rs.next()){
Object[] objects = new Object[colNo];
// tanks to umit ozkan for the bug fix!
for(int i=0;i<colNo;i++){
objects[i]=rs.getObject(i+1);
}
aModel.addRow(objects);
}
aTable.setModel(aModel);

Detect SQL error or warning


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0331.html

Fix incomplete field returned by the ResultSet 432


Real's HowTo PDF version

Warning

When the database server executes an SQL statement successfully, but encounters a warning condition, it
sets the SQLSTATE class field to "01". The subclass code then indicates the cause of the warning. This
warning can be an ANSI or X/Open warning message (if supported by the driver) the subclass code in the
range "000" to "006". Also the driver can provide is own warning codes in the "01" class.

Class Subclass
01 000 Success with warning

01 002 Disconnect error-transaction rolled back

01 003 Null value eliminated in set function

01 004 String data, right truncation

01 005 Insufficient item descriptor areas

01 006 Privilege not revoked

01 007 PRIVILEGE NOT GRANTED

The JDK API doc reveals that "The SQLWarning class provides information on a database access
warnings. Warnings are silently chained to the object whose method caused it to be reported". So after DB
operation, you ask the Connection object if there are any warnings. Depending on the vendor driver,
informations (not only Warnings) can be found in the SQLWarning object.

dbConn = DriverManager.getConnection
("jdbc:odbc:YourDatabaseName","username","password");
SQLWarning w = dbConn.getWarnings();
// If a SQLWarning object was returned by the
// Connection object, the warning messages are displayed.
// You may have multiple warnings chained together
if (w != null) {
System.out.println ("\n *** SQL Warning ***\n");
while (w != null) {
System.out.println ("Message: " + w.getMessage ());
System.out.println ("SQLState: " + w.getSQLState ());
System.out.println ("VendorCode: " + w.getErrorCode ());
System.out.println ("");
w = w.getNextWarning ();
}
}
}

Error

When an error occurs, a SQLException is thrown. You can interrogate the SQLException object to know
more details about the actual error. Note that SQLException can be chained. The SQLException object

Detect SQL error or warning 433


Real's HowTo PDF version

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.

Make DSN-less connection


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0345.html

This HowTo is deprecated. For Java 8 you cannot use the JDBC-ODBC Bridge because it has been
removed.

Make DSN-less connection 434


Real's HowTo PDF version

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.

Select a CharSet when connecting to DBMS


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0371.html

Class.forName(sun.jdbc.odbc.JdbcOdbcDriver) ;

// setup the properties


java.util.Properties prop = new java.util.Properties();
prop.put("charSet", "iso-8859-7"); // for example...
prop.put("user", username);
prop.put("password", password);

// Connect to the database


con = DriverManager.getConnection(url, prop);

List tables in a database


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0317.html

import java.net.URL;
import java.sql.*;

Select a CharSet when connecting to DBMS 435


Real's HowTo PDF version

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

void disconnect() {
try {
dbConn.close();
}
catch (Exception e) {
e.printStackTrace();
}

List tables in a database 436


Real's HowTo PDF version

}
}

Enable JDBC logging


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0411.html

[JDK1.2]

Take the following program.

import java.net.URL;
import java.sql.*;

class JDBCapp {
static MyConnection theConn;

public static void main (String args[]) {


new JDBCapp().doit();
}

public void doit() {


theConn = new MyConnection();
theConn.connect("EAS Demo DB V3", "dba", "sql");

PreparedStatement prepstmt;
try {
prepstmt = theConn.dbConn.prepareStatement
("SELECT emp_id FROM employee" );
prepstmt.execute();
prepstmt.close();
}
catch (Exception e) { e.printStackTrace(); }
theConn.disconnect();
}
}

class MyConnection {
Connection dbConn = null;
void connect(String db, String user, String passw) {
try {
Driver d =
(Driver)Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
String URL = "jdbc:odbc:" + db;
dbConn = DriverManager.getConnection(URL, user, passw);
java.io.PrintWriter w =
new java.io.PrintWriter
(new java.io.OutputStreamWriter(System.out));
DriverManager.setLogWriter(w);

Enable JDBC logging 437


Real's HowTo PDF version

}
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

Detect if a table exists


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0485.html

Connection c = ...
DatabaseMetaData dbm = c.getMetaData();
// check if "employee" table is there
ResultSet tables = dbm.getTables(null, null, "employee", null);

Detect if a table exists 438


Real's HowTo PDF version

if (tables.next()) {
// Table exists
}
else {
// Table does not exist
}

Convert a ResultSet in XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0511.html

import java.sql.Connection;
import java.sql.Statement;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

class JDBCapp {

static Connection con;

public static void main (String args[]) {


ResultSet rs = null;
Statement stmt = null;
String sql;

try {
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder =factory.newDocumentBuilder();
Document doc = builder.newDocument();
Element results = doc.createElement("Results");
doc.appendChild(results);

// connection to an ACCESS MDB


con = AccessCon.getConnection();

sql = "select objet from Email";


stmt = con.createStatement();
rs = stmt.executeQuery(sql);

Convert a ResultSet in XML 439


Real's HowTo PDF version

ResultSetMetaData rsmd = rs.getMetaData();


int colCount = rsmd.getColumnCount();

while (rs.next()) {
Element row = doc.createElement("Row");
results.appendChild(row);
for (int ii = 1; ii <= colCount; ii++) {
String columnName = rsmd.getColumnName(ii);
Object value = rs.getObject(ii);
Element node = doc.createElement(columnName);
node.appendChild(doc.createTextNode(value.toString()));
row.appendChild(node);
}
}

System.out.println(getDocumentAsXml(doc));

}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
if (con != null) con.close();
if (stmt != null) stmt.close();
if (rs != null) rs.close();
}
catch (Exception e) {
}
}
}

public static String getDocumentAsXml(Document doc)


throws TransformerConfigurationException, TransformerException {
DOMSource domSource = new DOMSource(doc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
//transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,"yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1");
// we want to pretty format the XML output
// note : this is broken in jdk1.5 beta!
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
java.io.StringWriter sw = new java.io.StringWriter();
StreamResult sr = new StreamResult(sw);
transformer.transform(domSource, sr);
return sw.toString();
}
}

Convert a ResultSet in XML 440


Real's HowTo PDF version

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

*/
}
}

Display ResultSet data in an HTML Table in Servlet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0378.html

private int dumpData(java.sql.ResultSet rs, java.io.PrintWriter out)


throws Exception {
int rowCount = 0;

out.println("<P ALIGN='center'><TABLE BORDER=1>");


ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
// table header
out.println("<TR>");
for (int i = 0; i < columnCount; i++) {
out.println("<TH>" + rsmd.getColumnLabel(i + 1) + "</TH>");
}
out.println("</TR>");
// the data
while (rs.next()) {
rowCount++;
out.println("<TR>");
for (int i = 0; i < columnCount; i++) {
out.println("<TD>" + rs.getString(i + 1) + "</TD>");
}
out.println("</TR>");
}
out.println("</TABLE></P>");
return rowCount;
}

Display ResultSet data in an HTML Table in Servlet 441


Real's HowTo PDF version

Escape special character in a LIKE clause


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0554.html

Your JDBC driver may support the {escape 'escape character'} syntax for using LIKE clause wildcards as
literals. The escape sequence must be at the end of the SQL statement.

Searching for "one_word"

st = con.createStatement();
rs = st.executeQuery
("SELECT value FROM vendors WHERE value LIKE 'one/_word' {escape '/'}");

Searching for strings ending with "one%word"

st = con.createStatement();
rs = st.executeQuery
("SELECT value FROM vendors WHERE value LIKE '%one/%word' {escape '/'} ");

Find all rows in which a begins with the character "%"

st = con.createStatement();
rs = st.executeQuery
("SELECT value FROM vendors WHERE value LIKE '$%%' {escape '$'}");

Find all rows in which a ends with the character "_"

st = con.createStatement();
rs = st.executeQuery
("SELECT value FROM vendors WHERE 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 : Labo-Oracle.com.

Log the SQL Statements


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0602.html

Escape special character in a LIKE clause 442


Real's HowTo PDF version

Plain JDBC Logging

See this HowTo.

P6Spy

P6Spy is an open source framework for applications that intercept and optionally modify database
statements.

The log file format is

current time|execution time|category|statement SQL String|effective SQL string

P6Spy is especially useful with an application server.

Download at http://p6spy.com/

It is a bit old, the latest release is 2003!

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/

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/

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/

Log the SQL Statements 443


Real's HowTo PDF version

Oracle JDBC

Oracle driver provides some debugging infos. See this HowTo

Insert data in batch mode


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0658.html

The regular approach

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import 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

Log the SQL Statements 444


Real's HowTo PDF version

The performance gain is good. For example, 100 individual INSERTS == 140ms 10 batched INSERTS ==
32ms

Using PreparedStatement in batch mode

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import 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.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 java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import 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");

Insert data in batch mode 445


Real's HowTo PDF version

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

Retrieve large ResultSet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0659.html

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 10-row 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 java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class PerfSelect {


public static void main(String[] args) throws ClassNotFoundException,
SQLException, IOException {
Class.forName("oracle.jdbc.driver.OracleDriver");

Retrieve large ResultSet 446


Real's HowTo PDF version

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 (def == 10)


48296 ms
48045 ms

prefetch == 100
14859
14749

prefetch == 200
13343
13296

prefetch == 500
13891
13812

prefetch == 1000
13078
13078

*/

Handle dates
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0114.html

Handle dates 447


Real's HowTo PDF version

To get the current date in SQL format.

java.util.Date today =
new java.util.Date();
java.sql.Date sqlToday =
new java.sql.Date(today.getTime());

For Timestamp, it's the same idea

java.util.Date today =
new java.util.Date();
java.sql.Timestamp now =
new java.sql.Timestamp(today.getTime());

To use a Date, Time or Timestamp in a query, you can use JDBC escape codes.

Date {d 'yyyy-mm-dd'}
Time {t {'hh:mm:ss'}
Timestamp {ts `yyyy-mm-dd hh:mm:ss.f . . .'}
note: the .f .... is optional

For example, a Statement with a Date will look like this

java.util.Date today =
new java.util.Date();
java.sql.Date sqlToday =
new java.sql.Date(today.getTime());

String query =
"select * from cust where purchase_date <{ d '"
+ sqlDate.toString() + "' }");

With a PreparedStatement, you don't need JDBC escape codes, the JDBC driver will do the job for you.

java.util.Date today =
new java.util.Date();
java.sql.Date sqlToday =
new java.sql.Date(today.getTime());

PreparedStatement p = theConn.prepareStatement
("select * from cust where purchase_date <?");
p.setDate(1, sqlToday);
ResultSet rs = p.executeQuery();

To INSERT

PreparedStatement p = theConn.prepareStatement
("insert into TableWithADateColumn values(?)");
p.setDate(1, sqlToday);
p.executeUpdate();

Handle dates 448


Real's HowTo PDF version

or

p.executeUpdate
("insert into TableWithADateColumn values( { d '1999-12-31' } )");

One thing to remember when using java.sql.date is (according to the javadoc) :

To conform with the definition of SQL DATE, the millisecond values


wrapped by a java.sql.Date instance must be 'normalized' by setting
the hours, minutes, seconds, and milliseconds to zero in the particular
time zone with which the instance is associated.

Get current date using JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0383.html

With most DBMS, JDBC function escape sequence can be used :

SELECT {fn curdate() } for current date


SELECT {fn curtime() } for current hour
SELECT {fn now() } for current date and hour

for Oracle, you add the from dual

SELECT {fn curdate() } FROM dual for current date


SELECT {fn curtime() } FROM dual for current hour
SELECT {fn now() } FROM dual for current date and hour

Example :

// for Oracle
String sql =
"select {fn dayname ({fn now()})}," +
" {d '1997-05-24'}, " +
" {t '10:30:29' }, " +
" {ts '1997-05-24 10:30:29.123'}" +
" from dual" ;

ResultSet rs = stmt.executeQuery(sql);

while (rs.next())
System.out.println("results: " + rs.getString(1) +
"\n " + rs.getString(2) +
"\n " + rs.getString(3) +
"\n " + rs.getString(4) );

Get current date using JDBC 449


Real's HowTo PDF version

Insert the current date


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0567.html

It's good idea to use the JDBC escape function instead of using a specific DBMS function. This way, your
code will be portable.

sql = "INSERT INTO CUSTOMERS VALUES("


+ "'" + custName + "'" + ","
+ "'" + custPhone + "'" + ","
+ " {fn now() } )";

Read Excel worksheet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0362.html

This HowTo is deprecated. For Java 8 you cannot use the JDBC-ODBC Bridge because it has been
removed.
Let's assume we have a worksheet like this
LASTNAME FIRSTNAME ID
Reiser Beth 102
Ricci Dylan 111
Gugliuzza Brian 116

To access this data, we can use the JDBC-ODBC bridge. Microsoft provides an ODBC driver to Excel
worksheet.

Define an ODBC datasource (system DSN) named "employee_xls" that points to that worksheet.

example 1

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

public class EmployeeReader{


public static final String DRIVER_NAME =
"sun.jdbc.odbc.JdbcOdbcDriver";
public static final String DATABASE_URL = "jdbc:odbc:employee_xls";

public static void main(String[] args)


throws ClassNotFoundException, SQLException{

Insert the current date 450


Real's HowTo PDF version

Class.forName(DRIVER_NAME);
Connection con = null;
try {
con = DriverManager.getConnection(DATABASE_URL);
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery
("select lastname, firstname, id from [Sheet1$]");
while (rs.next()) {
String lname = rs.getString(1);
String fname = rs.getString(2);
int id = rs.getInt(3);

System.out.println(fname + " " + lname + " id : " + id);


}
rs.close();
stmt.close();
}
finally {
if (con != null)
con.close();
}
}
}

example 2

import java.io.*;
import java.sql.*;

public class EmployeeReader{


public static void main(String[] args){
Connection connection = null;
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con = DriverManager.getConnection( "jdbc:odbc:employee_xls" );
Statement st = con.createStatement();
ResultSet rs = st.executeQuery( "Select * from [Sheet1$]" );

ResultSetMetaData rsmd = rs.getMetaData();


int numberOfColumns = rsmd.getColumnCount();

System.out.println ( "No of cols "+numberOfColumns );

while (rs.next()) {
for (int i = 1; i <= numberOfColumns; i++) {
if (i > 1) System.out.print(", ");
String columnValue = rs.getString(i);
System.out.print(columnValue);
}
System.out.println("");
}
rs.close();
st.close();
}

Read Excel worksheet 451


Real's HowTo PDF version

catch(Exception ex) {
System.err.print("Exception: ");
System.err.println(ex.getMessage());
}
finally {
con.close();
}
}
}

Handle Excel files


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0516.html

There are many solutions to read or write Excel spreadsheets from Java. This HowTo is only about
OpenSource (and free) solutions.

JDBC-ODBC Excel driver

For Java 8 you cannot use the JDBC-ODBC Bridge because it has been removed.
This solution lets you access your Excel worksheet with SQL SELECT statement. The required ODBC
driver is included in a regular Windows installation and the JDBC-ODBC bridge is used to access the Excel
DSN.

See this HowTo for an example.

JExcel

Java Excel API is a java API enabling developers to read, write, and modify Excel spreadsheets
dynamically. Any operating system which can run a Java virtual machine can both process and deliver
Excel spreadsheets. One nice thing about JExcelApi is that it has no dependencies on any third party
libraries.

Example : output an Excel file from a Servlet

import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

Handle Excel files 452


Real's HowTo PDF version

public class Sample extends HttpServlet {


public void doGet
(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
OutputStream out = null;
try {
response.setContentType("application/vnd.ms-excel");
response.setHeader
("Content-Disposition", "attachment; filename=sampleName.xls");
WritableWorkbook w =
Workbook.createWorkbook(response.getOutputStream());
WritableSheet s = w.createSheet("Demo", 0);
s.addCell(new Label(0, 0, "Hello World"));
w.write();
w.close();
}
catch (Exception e){
throw new ServletException("Exception in Excel Sample Servlet", e);
}
finally{
if (out != null)
out.close();
}
}
}

See http://jexcelapi.sourceforge.net/

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

Handle Excel files 453


Real's HowTo PDF version

fileOut.close();

The name was originally an acronym for "Poor Obfuscation Implementation" (ref: Wikipedia).

See http://jakarta.apache.org/poi/

JXLS

jXLS is a project that allows creation of extremely complex Excel reports just in several lines of code. It is
based on Jakarta POI.

With jXLS, all you need is to create XLS template file with all required formatting, formulas etc using
specific notation to indicate placement of data and then write a couple lines of code to invoke jXLS engine
passing XLS template and the exported data as parameters.

Example :
The XLS Template

Employees
Name Age Payment Bonus
${employee.name} ${employee.age} ${employee.payment} ${employee.bonus}
$[SUM(@employee.payment@)]

with the code

Collection staff = new HashSet();


staff.add(new Employee("Derek", 35, 3000, 0.30));
staff.add(new Employee("Elsa", 28, 1500, 0.15));
Map beans = new HashMap();
beans.put("employee", staff);
XLSTransformer transformer = new XLSTransformer();
transformer.transformXLS(templateFileName, beans, destFileName);

gives the result

Employees
Name Age Payment Bonus
Derek 35 3000 30,00%
Else 28 1500 15,00%
4500

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;

Handle Excel files 454


Real's HowTo PDF version

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/

xlSQL

xlSQL is a JDBC Driver for Excel and CSV data sources. Documents can be read and written with SQL as
if they were tables in a database.

You can export XLS to XML or SQL INSERT statements. xlSQL includes its own "zero-admin" mySQL
database. The documentation is minimal at this time.

See http://xlsql.sourceforge.net/

JCOM

JCOM is a Java to COM bridge library. With JCOM you can call a COM object from Java as if it were a
Java object without having to deal with the internals of JNI. The documentation is minimal (in Japanese!).

Example :

import jp.ne.so_net.ga2.no_ji.jcom.excel8.*;
import jp.ne.so_net.ga2.no_ji.jcom.*;
import java.io.File;
import java.util.Date;

class TestExcel {
public static void main(String[] args) throws Exception {
ReleaseManager rm = new ReleaseManager();
try {
System.out.println("EXCEL startup...");
// if already started, open new window
ExcelApplication excel = new ExcelApplication(rm);
excel.Visible(true);
// display any information
System.out.println("Version="+excel.Version());
System.out.println("UserName="+excel.UserName());
System.out.println("Caption="+excel.Caption());
System.out.println("Value="+excel.Value());

Handle Excel files 455


Real's HowTo PDF version

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

System.out.println("thank you .");


}

Handle Excel files 456


Real's HowTo PDF version

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.

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

Handle Excel files 457


Real's HowTo PDF version

(workingdir + "testImages.gif");

// add to sheet
ImageHandle giffy = new ImageHandle(fin, sheet);

// set picture size and location in sheet


giffy.setBounds(100, 100, 400, 200);
giffy.setName("giffy");
sheet.insertImage(giffy);

// add to sheet
for(int x=0;x<100;x++) {
fin = new FileInputStream(workingdir + "testImages.png");
ImageHandle jpgy = new ImageHandle(fin, sheet);
jpgy.setName("heart" + x);
// set the random x/y coords of picture
int ix = Math.round((float)((x * (Math.random()*10))));
jpgy.setX(100 + ix);
ix = Math.round((float)((x * (Math.random()*10))));
jpgy.setY(100 + ix);
sheet.insertImage(jpgy);
}
// get png image input stream
fin = new FileInputStream(workingdir + "testImages.jpg");
// add to sheet
ImageHandle pngy = new ImageHandle(fin, sheet);
// set just the x/y coords of picture
pngy.setX(10);
pngy.setY(200);
sheet.insertImage(pngy);
}
catch(Exception e){
System.err.println("testImages failed: " + e.toString());
}
testWrite(tbo, workingdir + "testImagesOut.xls");
WorkBookHandle newbook = new WorkBookHandle
(workingdir + "testImagesOut.xls",0);
System.out.println("Successfully read: " + newbook);
}

public void testWrite(WorkBookHandle b, String fout){


try{
java.io.File f = new java.io.File(fout);
FileOutputStream fos = new FileOutputStream(f);
BufferedOutputStream bbout = new BufferedOutputStream(fos);
bbout.write(b.getBytes());
bbout.flush();
fos.close();
}
catch (java.io.IOException e){
System.err.println("IOException in Tester. "+e);
}
}

Handle Excel files 458


Real's HowTo PDF version

See also this HowTo for a way to create a simple XLS without any additional library.

Connect to an Oracle database with JDBC


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

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

Connect to an Oracle database with JDBC 459


Real's HowTo PDF version

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 java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import 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 () throws SQLException {


String usr = "scott";
String pwd = "tiger";
String url = "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);
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();

Connect to an Oracle database with JDBC 460


Real's HowTo PDF version

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.

Connect to Oracle using a connection pool


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0545.html

The Oracle thin jdbc driver (v9.2) makes it very easy to use a connection pool, it's all built in the
OracleDataSource with the implicit connection cache mechanism.

An application turns the implicit connection cache on by invoking


OracleDataSource.setConnectionCachingEnabled(true). After implicit caching is turned on, the first
connection request to the OracleDataSource transparently creates a connection cache.

After you have turned connection caching on, whenever you retrieve a connection through an
OracleDataSource.getConnection(), the JDBC drivers check to see if a connection is available in the
cache.The getConnection() method checks if there are any free physical connections in the cache that match
the specified criteria. If a match is found, a logical connection is returned wrapping the physical connection.
If no physical connection match is found, a new physical connection is created, wrapped in a logical
connection, and returned.

A Connection Pool is a cache of database connections maintained in memory so that the connections can be
reused when the database receives future requests for data. Connection pools are used to enhance the
performance of executing commands on a database. Various parameters such as number of minimum

Connect to Oracle using a connection pool 461


Real's HowTo PDF version

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

Connect to Oracle using a connection pool 462


Real's HowTo PDF version

public static Connection getConnection(String env)


throws SQLException
{
System.out.println("Request connection for " + env);
if (ods == null) {
throw new SQLException("OracleDataSource is null.");
}
return ods.getConnection();
}

public static void closePooledConnections() throws SQLException{


if (ods != null ) {
ods.close();
}
}

public static void listCacheInfos() throws SQLException{


OracleConnectionCacheManager occm =
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));

Connect to Oracle using a connection pool 463


Real's HowTo PDF version

stmt.close();
System.out.println ("Ok.");
JDBCUtils.listCacheInfos();
conn.close();

}
catch (SQLException e) {
e.printStatckTrace()
}
finally {
System.out.println ("Sleep... " + noThread);
try {
Thread.sleep(1000);
}
catch(Exception e) { }
}
}
}

and finally, the main class

import java.net.URL;
import java.sql.*;

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

Retrieve the generated keys (JDBC Oracle)


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

Retrieve the generated keys (JDBC Oracle) 464


Real's HowTo PDF version

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

Debug Oracle JDBC connection


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

Debug Oracle JDBC connection 465


Real's HowTo PDF version

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
#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 sub-module filters do not
# apply to messages of this category. See also
# enableWarning().
# (expected volume: low)
#
# FUNCTION Function entry/return information.

Debug Oracle JDBC connection 466


Real's HowTo PDF version

# FINE (expected volume: medium)


#
# DEBUG1 High-level 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

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

Connect to an Oracle database using Kerberos


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-oracle-jdbc-connect-with-kerberos.html

Connect to an Oracle database using Kerberos 467


Real's HowTo PDF version

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 java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import 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(
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();
}
}

Connect to an Oracle database using Kerberos 468


Real's HowTo PDF version

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

Identify the connected program to an Oracle database


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-oracle-jdbc-identify-connection-origin.html

The v$session view contains session information for each current session.

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 java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import 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");

Identify the connected program to an Oracle database 469


Real's HowTo PDF version

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 :

|username |osuser. |program |machine


|bigadmin |real |JDBC Thin Client |Jupiter
|real |real |Winsql.exe |Saturn
|scott |real |My Java program : TestOra5 |Mercury

Use a CHAR field in the WHERE clause in a PreparedStatement


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-oracle-char-field-preparedstatement.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.

Use a CHAR field in the WHERE clause in a PreparedStatement 470


Real's HowTo PDF version

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 is 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.

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

Use a CHAR field in the WHERE clause in a PreparedStatement 471


Real's HowTo PDF version

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 we are not using a special Oracle class and the database will use the index.

Written and compiled Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Use a CHAR field in the WHERE clause in a PreparedStatement 472


JNI/JNA
java-jni

Use native code through JNI (HelloWorld)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0283.html

• With MSVC6, create a new Win32 DLL project (simple) and call it javahowto.
• In the same directory create a java source called JavaHowTo.java
class JavaHowTo {
public native String sayHello();
static {
System.loadLibrary("javahowto");
}
}
• Compile the Java program and use javah utility to generate the JavaHowTo.h header file.
javah -jni JavaHowTo
• In MSVC6, add the JavaHowTo.h in your project header files
• In the Tools - Options menu, set the include directories to include the Java JNI headers files. They are
located in [jdk dir]\include and [jdk dir]\include\win32 directories
• In the javahowto.cpp source, add
#include "JavaHowTo.h"

JNIEXPORT jstring JNICALL Java_JavaHowTo_sayHello


(JNIEnv *env, jobject obj) {
return env->NewStringUTF("Hello world");
}
• Select the Release configuration and build the project.
• Copy the javahowto.dll in the same directory as the java program.
• Create this new java program
public class JNIJavaHowTo {
public static void main(String[] args) {
JavaHowTo jht = new JavaHowTo();
System.out.println(jht.sayHello());
}
}
• Compile and execute.

Pass string to/from Java to/from C


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0284.html

JNI/JNA 473
Real's HowTo PDF version

To Java from C (as seen from the previous How-to) :

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

Pass string to/from Java to/from C 474


Real's HowTo PDF version

public native void sayHello();


static {
System.loadLibrary("javahowto");
}
}

And finally, to use it

public class JNIJavaHowTo {


public static void main(String[] args) {
JavaHowTo jht = new JavaHowTo();
jht.sayHello();
}
}

Set the computer clock


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0285.html

Define the following prototype in the header file

JNIEXPORT void JNICALL Java_JavaHowTo_setSystemTime


(JNIEnv *, jobject, jshort, jshort);

the JNI function

JNIEXPORT void JNICALL Java_JavaHowTo_setSystemTime


(JNIEnv *env, jobject obj, jshort hour, jshort minutes) {

SYSTEMTIME st;

GetLocalTime(&st);
st.wHour = hour;
st.wMinute = minutes;
SetLocalTime(&st);
}

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

Set the computer clock 475


Real's HowTo PDF version

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

Determine the signature of a method


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0286.html

Before calling a Java object's method from JNI, we need its signature. For example, the method

long myMethod (int n, String s, int[] arr);

is seen from JNI with the signature

(ILJAVA/LANG/STRING;[I)J

There are two parts to the signature. The first part is enclosed within the parentheses and represents the
method's arguments. The second portion follows the closing parenthesis and represents the return type. The
mapping between the Java type and C type is

Type Chararacter
boolean Z
byte B
char C
double D
float F
int I
long J
object L
short S
void V
array [

Note that to specify an object, the "L" is followed by the object's class name and ends with a semi-colon, ';' .

The javap utility (included with the JDK) is very useful to show the signature to be used in JNI.

Determine the signature of a method 476


Real's HowTo PDF version

X:\>javap -s java.awt.Label
Compiled from Label.java
public class java.awt.Label extends java.awt.Component {
public static final int LEFT;
/* I */
public static final int CENTER;
/* I */
public static final int RIGHT;
/* I */
java.lang.String text;
/* Ljava/lang/String; */
int alignment;
/* I */
static {};
/* ()V */
public java.awt.Label();
/* ()V */
public java.awt.Label(java.lang.String);
/* (Ljava/lang/String;)V */
public java.awt.Label(java.lang.String,int);
/* (Ljava/lang/String;I)V */
public void addNotify();
/* ()V */
java.lang.String constructComponentName();
/* ()Ljava/lang/String; */
public int getAlignment();
/* ()I */
public java.lang.String getText();
/* ()Ljava/lang/String; */
protected java.lang.String paramString();
/* ()Ljava/lang/String; */
public synchronized void setAlignment(int);
/* (I)V */
public void setText(java.lang.String);
/* (Ljava/lang/String;)V */

The javap utility can be used on the java.* or your own classes.

Use arrays
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0287.html

JNI provides special functions (relative to the type) to access Java arrays.

This example returns the maximum of an int array.

JNIEXPORT jint JNICALL Java_JavaHowTo_max


(JNIEnv * env, jclass obj, jintArray arr) {
int i;

Use arrays 477


Real's HowTo PDF version

jsize len = env->GetArrayLength(arr, max = -1;


jint *body = env->GetIntArrayElements(arr, 0);
for (max = body[0], i=1; i <len; i++)
if (max <body[i]) max = body[i];
env->ReleaseIntArrayElements(arr, body, 0);
return max;
}

The Java wrapper

class JavaHowTo {
public static native int max(int [] t);
static {
System.loadLibrary("javahowto");
}
}

The test program

class JNIJavaHowTo {
public static void main(String[] args) {
int [] myArray = {4, 7, 5, 9, 2, 0, 1};
System.out.println(JavaHowTo.max(myArray));
}
}

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_64-w64-mingw32-gcc).

Use arrays 478


Real's HowTo PDF version

#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, &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);
}

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

Load a DLL
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0318.html

[pre JDK1.2]

System.loadLibrary("d:\\directoryX\\subDirY\\MyDll.dll")

In JDK1.2 (or better), if the DLL is in the CLASSPATH then you don't need to specify a PATH. If the DLL is
not in the CLASSPATH then you need to specify the PATH.

Do something like this instead.

Runtime.getRuntime().load("d:/directoryX/subDirY/MyDll.dll");

or specify through the JVM command line the location where to find the JNI DLL to be loaded

Load a DLL 479


Real's HowTo PDF version

java -Djava.library.path=c:/temp JNIJavaHowTo

Use the MouseWheel


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0314.html

Current JDK don't support scrolling via the MouseWheel.

Next version (JDK1.4) may provide this functionality but for now, you need some JNI functions.

See this link http://www.codeproject.com/java/mousewheel.asp .

Throw an exception in JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0323.html

Define the following prototype in the header file

JNIEXPORT jdouble JNICALL Java_JavaHowTo_divide


(JNIEnv *, jobject, jdouble, jdouble);

the JNI function

JNIEXPORT jdouble JNICALL Java_JavaHowTo_divide


(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

Use the MouseWheel 480


Real's HowTo PDF version

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

Throw my own exception in JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0322.html

The MyOwnException class

public class MyOwnException extends Exception {


public MyOwnException(){}
public MyOwnException(String txt) {
super(txt);
}
}

the prototype in the header file

JNIEXPORT void JNICALL Java_JavaHowTo_triggerException


(JNIEnv *, jobject);

the JNI function

JNIEXPORT void JNICALL Java_JavaHowTo_triggerException


(JNIEnv *env, jobject obj) {
jclass MyOwnException = env->FindClass("MyOwnException");
env->ThrowNew(MyOwnException,"Exception triggered from JNI routine.");
}

The Java JNI wrapper would be

class JavaHowTo {
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();

Throw an exception in JNI 481


Real's HowTo PDF version

jht.triggerException();
}
}

JNI from a Package


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0348.html

JNI requires that the function names follow a specific format. If you have a Java native method in a class
called MyClass like this:

public native void myMethod();

the native function must look like this:

JNIEXPORT void JNICALL Java_MyClass_myMethod(JNIEnv *, jobject);

When you put the class into a package (say com.rgagnon), you need to include the package information in the
native function name like this:

JNIEXPORT void JNICALL Java_com_rgagnon_MyClass_myMethod(JNIEnv *, jobject);

To generated the proper header, compile the JNI class in the package then, using the javah utility (from the
root of the package) :

javah com.rgagnon.MyClass

Make a Window stay on top


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0353.html

First you need the handle of the Window. Call this JNI function with Window Title.

JNIEXPORT jint JNICALL Java_JavaHowTo_getHwnd


(JNIEnv *env, jclass obj, jstring title){
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;
}

Throw my own exception in JNI 482


Real's HowTo PDF version

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

Start JVM from C


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0354.html

#include <jni.h>
#include <stdio.h>

int main() {
JavaVM *vm;
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options[1];
options[0].optionString = "-Djava.class.path=c:/myclasses";
vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
vm_args.nOptions = 1;
vm_args.ignoreUnrecognized = 1;
jstring jstr;
jobjectArray args;
jint res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args);
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);

Make a Window stay on top 483


Real's HowTo PDF version

if (args == 0) {
printf("Out of memory\n");
exit(1);
}
env->CallStaticVoidMethod(cls, mid, args);
return 0;
}

Retrieve environment variable (JNI)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0460.html

For some odd reasons, the getenv() method was removed from the JDK. Rumors is that a mechanism to
retrieve an environment will be back in JDK1.5 (see this HowTo). But for now, you can use -D switch to
retrieve named environment variable and pass them to the JVM (see this HowTo) or use this JNI routine :

JNIEXPORT jstring JNICALL JavaHowTo_getenv


(JNIEnv *env, jclass c, jstring jname){
if ( jname == NULL ) {
return NULL ;
}
const char *name =
(*env)->GetStringUTFChars(env, jname, (jboolean *)NULL) ;
const char *value = getenv(name) ;
(*env)->ReleaseStringUTFChars(env, jname, name) ;
return value ? (*env)->NewStringUTF(env, value) : NULL ;
}

NOTE : This is fine if the environment variable contains only regular 7-bit ASCII characters.

See also this HowTo.

Get the PID


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0467.html

class JavaHowTo {
public native long getCurrentProcessId();
static {
System.loadLibrary("jni2");
}
}

public class JNIJavaHowTo {

Start JVM from C 484


Real's HowTo PDF version

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 Java-only solution, see this HowTo

Clear the console, set color and cursor position (JNI)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0469.html

[Windows only]
First you need this Java stub (JavaHowTo.java) to provide an interface to the JNI DLL (jni3.dll).

class JavaHowTo {

public static final short FOREGROUND_BLACK = 0x0;


public static final short FOREGROUND_BLUE = 0x1;

Get the PID 485


Real's HowTo PDF version

public static final short FOREGROUND_GREEN = 0x2;


public static final short FOREGROUND_RED = 0x4;
public static final short FOREGROUND_WHITE = 0x7;
public static final short FOREGROUND_INTENSITY = 0x8;

public static final short BACKGROUND_BLUE = 0x10;


public static final short BACKGROUND_GREEN = 0x20;
public static final short BACKGROUND_RED = 0x40;
public static final short BACKGROUND_INTENSITY = 0x80;
// and so on...the definition for the other colors is
// left as an exercise :-)

public native void cls();


public native void setCursorPosition( short x, short y);
public native void keepColors();
public native void restoreColors();
public native void setColor( short foreground, short background);
static {
System.loadLibrary("jni3");
}
}

Compile and generate an header with javah JavaHowto, the result is a file called JavaHowTo.h.

Next we built a DLL, I'm using VisualStudio v6. Don't forget to include the folders %JAVAHOME%\include
and %JAVAHOME%\include\win32 to have access to the JNI header files.

// jni3.cpp : Defines the entry point for the DLL application.


//

#include "stdafx.h"
#include <stdlib.h>
#include "JavaHowTo.h"

int originalColors;

BOOL APIENTRY DllMain( HANDLE hModule,


DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}

JNIEXPORT void JNICALL Java_JavaHowTo_cls


(JNIEnv *env, jobject obj) {

HANDLE hConsole;
unsigned long * hWrittenChars = 0;
CONSOLE_SCREEN_BUFFER_INFO strConsoleInfo;

Clear the console, set color and cursor position (JNI) 486
Real's HowTo PDF version

COORD Home;
static unsigned char EMPTY = 32;

Home.X = 0;
Home.Y = 0;
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &strConsoleInfo);
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);
}

JNIEXPORT void JNICALL Java_JavaHowTo_keepColors


(JNIEnv *env, jobject obj) {
HANDLE hConsole;
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;

hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &ConsoleInfo);
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.

Clear the console, set color and cursor position (JNI) 487
Real's HowTo PDF version

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.

Call Windows API (Open source solution)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0497.html

NativeCall
NativeCall is a Java toolkit that lets you call operating system methods from whithin Java without JNI code.

// copying a file to a new one using the Windows API


import com.eaio.nativecall.*;

NativeCall.init();
IntCall ic = new IntCall("CopyFileA");
ic.executeCall(new Object[] { "test.txt", "test_copy.txt", Boolean.FALSE });
ic.destroy();

Call Windows API (Open source solution) 488


Real's HowTo PDF version

See http://johannburkard.de/software/nativecall/

Detect if a program is running (JNA)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-detect-if-a-program-is-running-using-jna.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 : jna-3.5.1.jar and platform-3.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
}
}
}

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) or the free alternative WinID.

Detect if a program is running (JNA) 489


Real's HowTo PDF version

It is also possible to search for the class name and the title to make the search more precise.

See also this Howto

Close an external windows program using JNA


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-close-an-external-windows-program-using-jna.html

This example will close a running Powerpoint. The idea is to scan the Windows titles and find a match. If
found then the Windows message WinUser.WM_CLOSE is sent to the process using its handle.

import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.platform.win32.WinDef.HWND;

// https://github.com/twall/jna#readme
// you need 2 jars : jna-3.5.1.jar and platform-3.5.1.jar

public class KillMyPP {


public static void main(String[] args) {
HWND hwnd = User32.INSTANCE.FindWindow
(null, "Microsoft PowerPoint - [Présentation1]"); // window title
// you need to modify this
// for your need
if (hwnd == null) {
System.out.println("PPT is not running");
}
else{
User32.INSTANCE.PostMessage(hwnd, WinUser.WM_CLOSE, null, null); // can be WM_QUIT in s
}

Close an external windows program using JNA 490


Real's HowTo PDF version

}
}

You can make the search more precise by specifying the class name as the first parameter. You find the class
name of a specific Windows program with a special utility program like Spy++ or the free alternative WinID.
For PowerPoint, the class name is PP12FrameClass.

HWND hwnd = User32.INSTANCE.FindWindow


("PP12FrameClass", "Microsoft PowerPoint - [Présentation1]"); // class name and wi

You can search by the Windows title only, the class name only or with both.

To close Notepad

HWND hwnd = User32.INSTANCE.FindWindow


("Notepad", null); // class name
...
User32.INSTANCE.PostMessage(hwnd, WinUser.WM_CLOSE, null, null);

If there is a document to be saved you be prompted. To avoid that and discard the current document use the
WM_QUIT message instead of WM_CLOSE.

User32.INSTANCE.PostMessage(hwnd, WinUser.WM_QUIT, null, null);

If you want to kill all running instances, then you can loop until no handle is retrieved.

import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.platform.win32.WinDef.HWND;

// https://github.com/twall/jna#readme
// you need 2 jars : jna-3.5.1.jar and platform-3.5.1.jar

public class KillAllNotepad {


public static void main(String[] args) {
for (;;) {
HWND hwnd = User32.INSTANCE.FindWindow
("Notepad", null); // class name
if (hwnd == null) {
System.out.println("No Notepad instance detected");
break;
}
else{
System.out.println("Notepad instance found.");
User32.INSTANCE.PostMessage(hwnd, WinUser.WM_QUIT, null, null);
}
}
}
}

Close an external windows program using JNA 491


Real's HowTo PDF version

See also this Howto

Get Windows Special Folders (JNA)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-get-windows-special-folders-using-jna.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;
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 : jna-3.5.1.jar and platform-3.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
*/
}
}

Get Windows Special Folders (JNA) 492


Real's HowTo PDF version

See also : 1, 2 and 3

Written and compiled Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Get Windows Special Folders (JNA) 493


Javascript interaction
java-js

* Read me *
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0168.html

The examples in these How-to's are tested 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 pre-installed 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.

Wake-up a Java applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0169.html

When moving the mouse over an image, we want to start an applet (here a simple chronometer), and when the
mouse leave the image, the Applet should stop.

Javascript interaction 494


Real's HowTo PDF version

[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 = k-j;
currentTime = Long.toString(l/1000);
g.drawString(currentTime,10,30);
previousTime = currentTime;
}
}
}

class MyThread extends Thread {


JavaChrono theApplet;

public MyThread(JavaChrono a) {
theApplet = a;
}

public void run() {


while (true) {
try {
theApplet.repaint();
this.sleep(1000);

Wake-up a Java applet 495


Real's HowTo PDF version

}
catch(InterruptedException e) { }
}
}
}

[HTML]

<HTML><HEAD></HEAD><BODY>
<APPLET CODE=JavaChrono.class
WIDTH=150
HEIGHT=150>
</APPLET>
<A HREF=""
onMouseOver="document.applets[0].startChrono()"
onMouseOut="document.applets[0].stopChrono()" >
<IMG SRC="whatever.gif" WIDTH=100 HEIGHT=100>
</A>
&LT;/BODY&GT;&LT;/HTML&GT;

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()">
&LT;/FORM&GT;&LT;/BODY&GT;&LT;/HTML&GT;

[JAVA APPLET]

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

public class MyApplet extends Applet {


Frame f = null;

public void init() { }

public void showFrame() {

Wake-up a Java applet 496


Real's HowTo PDF version

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.

Call a Java method from Javascript


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0170.html

You call a Java method by giving its fully qualified name. In the following snippet, the first example calls the
method in the Toolkit to retrieve the screen resolution. The second example, calls a method in our Applet.

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

Call a Java method from Javascript 497


Real's HowTo PDF version

" width:" +
java.awt.Toolkit.getDefaultToolkit().getScreenSize().width +
" height:" +
java.awt.Toolkit.getDefaultToolkit().getScreenSize().height);
}
</SCRIPT>
<FORM>
<INPUT type="button" value="call Java Applet method"
onClick = "document.myApplet.sayHello()">
</FORM>

<INPUT type="button" value="call Java method direct"


onClick = "getScreenDimension()">

<APPLET CODE="InJava.class"
NAME="myApplet"
HEIGHT=100 WIDTH=100>
</APPLET>
&LT;/BODY&GT;&LT;/HTML&GT;

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>
&LT;/BODY&GT;&LT;/HTML&GT;

Call a Java method from Javascript 498


Real's HowTo PDF version

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.

Call a Java method from Javascript using DOM


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0346.html

[IE4 or better]
<OBJECT ID="myApplet" ...>
...
<PARAM NAME="scriptable" value="true">
<PARAM NAME="mayscript" value="true">
...
</OBJECT>

[in your script]


document.all.myApplet.myMethod()

You use the scriptable parameter if you call Java method from Javascript.
You use the mayscript parameter if you call Javascript function from Java.

This Sun's document describes how Java to Javascript communication works when using the Java Plug-in.

Access Java variables from Javascript


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0171.html

Java variables can be used by giving the fully qualified name. In Java, the variable must be declared as
"public". To be compatible Netscape AND MSIEv4, the preferred way is to use special "access method" to
read Java variables (only String or integer).

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

Call a Java method from Javascript using DOM 499


Real's HowTo PDF version

return iJava;
}
public String getStringJava() {
return sJava;
}
}

[Javascript and HTML]

<HTML><HEAD></HEAD><BODY>
<SCRIPT>
function JavaSays() {
alert("Java says\n the value of iJava is :" +
document.myApplet.getIntJava() + "\n" +
"and sJava is :" +
document.myApplet.getStringJava());
}
</SCRIPT>
<FORM>
<INPUT type="button" value="Java says"
onClick = "JavaSays();">
</FORM>
<APPLET CODE="InJava3.class"
NAME="myApplet"
HEIGHT=0 WIDTH=0>
&LT;/APPLET&GT;&LT;/BODY&GT;&LT;/HTML&GT;

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.

Call Javascript from a Java applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0172.html

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

Access Java variables from Javascript 500


Real's HowTo PDF version

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>
<APPLET CODE="InJava4.class"
NAME="myApplet" MAYSCRIPT
HEIGHT=10 WIDTH=10>
</APPLET>
</BODY>
&LT;/HTML&GT;

Try it here

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 java.applet.*;
import java.awt.*;
import java.awt.event.*;
import netscape.javascript.*;

public class InJava5 extends Applet implements ActionListener {


Button b;
TextField t;

Call Javascript from a Java applet 501


Real's HowTo PDF version

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

Call Javascript from a Java applet 502


Real's HowTo PDF version

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

Create dynamic HTML from a Java applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0173.html

We can use the netscape.javascript.* included with Netscape browser and IE4 (Win version). See also this
HowTo to learn how to compile with this package.

[Java applet JDK1.1 Netscape/IE4 (win) OK]

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

public class HtmlFromJava extends Applet


implements ActionListener {
Button aButton;

public void init(){


setLayout(new FlowLayout());
aButton = new Button("create HTML");
add(aButton);
aButton.addActionListener(this);
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == aButton){
String HTML = "<HTML><HEAD></HEAD><BODY>";
HTML += "<TABLE BORDER=1><TR><TD>Hello world</TD></TR></TABLE>";
HTML += "</BODY></HTML>";
JSObject win = (JSObject)JSObject.getWindow(this);
win.eval("createHTML(\"" + HTML +"\");");
}
}
}

Create dynamic HTML from a Java applet 503


Real's HowTo PDF version

[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>
&LT;/APPLET&GT;&LT;/BODY&GT;&LT;/HTML&GT;

Try it here

Inter-Applets communication across frames


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0174.html

You can use a Javascript function as a bridge between the 2 frames.

[main HTML (interframe0.html)]

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

[frame 1 HTML (interframe1.html)]

<HTML><HEAD></HEAD>
<SCRIPT>
function toOtherFrame(a, target) {
if (target == "f1")
parent.f1.document.app1.fromOtherFrame(a);
else
parent.f2.document.app2.fromOtherFrame(a);
}
</SCRIPT>
</HEAD>

<BODY>
<APPLET CODE="InterFrameDemo.class"

Inter-Applets communication across frames 504


Real's HowTo PDF version

NAME="app1" MAYSCRIPT
HEIGHT=200
WIDTH=200>
<PARAM NAME="target"
VALUE="f2">
</APPLET></BODY></HTML>

[frame 2 HTML (interframe2.html)]

<HTML><HEAD></HEAD>

<BODY>
<APPLET CODE="InterFrameDemo.class"
NAME="app2" MAYSCRIPT
HEIGHT=200
WIDTH=200>
WIDTH=200>
<PARAM NAME="target"
VALUE="f1">
</APPLET></BODY></HTML>

[Java applet (InterFrameDemo.java)]

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import netscape.javascript.*;

public class InterFrameDemo extends Applet implements ActionListener {


TextField tf;
Button b;
String target;

public void init() {


target = getParameter("target");
setLayout(new BorderLayout());
tf = new TextField(20);
add("South", tf);
b = new Button("To other frame");
add("North",b);
b.addActionListener(this);
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b) {
String js =
"parent.f1.toOtherFrame(\"" +
tf.getText() +
"\",\"" + target + "\")";
System.out.println("to Javascript:" + js);
JSObject win = (JSObject) JSObject.getWindow(this);
win.eval(js);

Inter-Applets communication across frames 505


Real's HowTo PDF version

}
}

public void fromOtherFrame(String s) {


tf.setText(s);
}
}

Try it here

For a JAVA-only solution check this Java How-to

Inter-Applet communication across pages


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0181.html

FirstApplet encodes the message for SecondApplet in the search (or query) section of SecondApplet.html
URL. A simple script in SecondApplet.html decodes the search section and dynamically creates a new page
containing the APPLET tag for SecondApplet and a PARAM with the message coming from FirstApplet.

FirstApplet.html

<HTML><HEAD></HEAD><BODY>
<APPLET CODE="FirstApplet.class"
HEIGHT=100
WIDTH=300>
&LT;/APPLET&GT;&LT;/BODY&GT;&LT;/HTML&GT;

FirstApplet.java

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

public class FirstApplet extends Applet implements


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

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b) {
try {

Inter-Applet communication across pages 506


Real's HowTo PDF version

getAppletContext().showDocument
(new URL(getCodeBase(),
"SecondApplet.html?" + "message="
+ URLEncoder.encode(t.getText())));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}

SecondApplet.html

<HTML><HEAD></HEAD><BODY>
<SCRIPT>
// from Javascript How-to general part 3,
// replace all occurrence of token by another
// in a string.
function replace(s, t, u) {
i = s.indexOf(t);
r = "";
if (i == -1) return s;
r += s.substring(0,i) + u;
if ( i + t.length <s.length)
r += replace(s.substring(i + t.length, s.length), t, u);
return r;
}

strlen = document.location.search.length
if (strlen > 0) {
theMessage = document.location.search
// strip the "message header"
theMessage = theMessage.substring(1 + 'message='.length,strlen)
// replace all '+" by space
theMessage = replace(theMessage, '+', ' ')
// replace encoded chars by decoded chars if any
theMessage = unescape(theMessage)
html = '<APPLET CODE="SecondApplet.class"'
html += ' HEIGHT=100'
html += ' WIDTH=400> '
html += '<PARAM NAME="Message" VALUE="' + theMessage + '"> '
html += '</APPLET>'
document.close()
document.open()
document.write(html)
document.close()
}
</SCRIPT>
&LT;/BODY&GT;&LT;/HTML&GT;

SecondApplet.java

Inter-Applet communication across pages 507


Real's HowTo PDF version

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

public class SecondApplet extends Applet {


public void init() {
Label l = new Label("Message from 1st Applet");
add (l);
TextField tf = new TextField( 50 );
add(tf);
String s = getParameter("Message");
tf.setText(s);
}
}

You can try it here!

This method is useful when you need to pass the message to the SecondApplet via PARAM tag. But if you
don't need the PARAM tag, take a look at this Java How-to.

Write HTML FORM values from a Java applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0175.html

Retrieve the value with a Javascript function called via the onSubmit event of the form.

[InitHTMLForm.java]

public class InitHTMLForm extends java.applet.Applet {


public String getFirstName() {
// in real life, you have TextField in your Applet and
// you want to transert its content to the HTML FORM
// return myTextField.getText();
return "Real's HowTo";
}
}

[HTML and Javascript]

<HTML><HEAD>
<SCRIPT>
function getValueFromApplet(){
document.myForm.q.value = document.myApplet.getFirstName();
return true;
}
</SCRIPT>
<BODY>
<APPLET CODE="InitHTMLForm.class"
NAME="myApplet"

Write HTML FORM values from a Java applet 508


Real's HowTo PDF version

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>
&LT;/BODY&GT;&LT;/HTML&GT;

Try it here

Detect if an Applet is ready


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0176.html

<SCRIPT>
function isAppletReady(a) {
return a.isActive();
}
</SCRIPT>

<FORM>
<INPUT TYPE=button
VALUE="Check applet"
onClick="if (!isAppletReady(document.applets[0])) alert("not ready");">
&LT;/FORM&GT;

An Applet is ready when it's loaded and its init() method is done.

To execute a Javascript only when an Applet is ready :

<SCRIPT>
function waituntilok() {
if (document.myApplet.isActive()) {
doit();
}
else {
settimeout(waituntilok(),5000)
}
}

function doit() {
....
}
</SCRIPT>
...
<BODY onLoad="waituntilok();">

Detect if an Applet is ready 509


Real's HowTo PDF version

....

&LT;/BODY&GT;

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>
&LT;/HTML&GT;

Read/Write HTML field values from Java


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0177.html

[Netscape AND IE4 compatible]


The netscape.javascript.* (LiveConnect) package provides facilities to directly manipulate HTML FORM
components.

Read/Write HTML field values from Java 510


Real's HowTo PDF version

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 java.applet.*;
import java.awt.event.*;
import java.awt.*;
import netscape.javascript.*;

public class JSjava extends Applet


implements ActionListener {
Button b1,b2;
TextField tf;

JSObject win;

public void init(){


setLayout(new FlowLayout());
tf = new TextField(10);
b1 = new Button("to FORM");
b2 = new Button("from FORM");

b1.addActionListener(this);
b2.addActionListener(this);
add(tf);add(b1);add(b2);
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b1) {
// send TO FORM
JSObject win = (JSObject)JSObject.getWindow(this);
win.eval("setHTMLInputText('"+tf.getText()+"');");
}
if (ae.getSource() == b2) {
// receive FROM FORM
JSObject win = (JSObject)JSObject.getWindow(this);
tf.setText((String)win.eval("getHTMLInputText();"));
}
}
}

Read/Write HTML field values from Java 511


Real's HowTo PDF version

[JSjava.html]

<HTML><HEAD>
<SCRIPT>
function getHTMLInputText(){
return document.forms[0].elements[0].value;
}
function setHTMLInputText(s){
document.forms[0].elements[0].value = s;
}
</SCRIPT></HEAD><BODY>
<FORM>
<INPUT TYPE=text SZIE=20>
</FORM>

<APPLET NAME="JS" CODE=JSjava.class MAYSCRIPT WIDTH=200 HEIGTH=200>


&LT;/APPLET&GT;&LT;/BODY&GT;&LT;/HTML&GT;

For best result, never use LiveConnect JSObject in Applet's init() method.

Detect if Java is enabled


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0178.html

from Javascript :

function isJavaAvailable(){
return ( navigator.javaEnabled && navigator.javaEnabled() );
}

For an HTML solution, check this How-to

Detect if Java 1.1 (with event delegation) is available


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0179.html

On some version of Netscape (eg.4.03), even if the JDK1.1 is reported as the Java version, you need to apply
a special patch to upgrade to the event delegation model. Here how you can detect if the patch has been
applied.

function isJava11Available() {
if (java.awt.event.MouseEvent)
return true;
else
return false;

Detect if Java is enabled 512


Real's HowTo PDF version

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.

Access Cookies from a Java Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0180.html

This Applet uses the package netscape.javascript.JSObject.

To compile such program, you have to include in the CLASSPATH 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>
&LT;/APPLET&GT;&LT;/BODY&GT;&LT;/HTML&GT;

[Java applet (TestCookie.java)]

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

public class TestCookie extends Applet


implements ActionListener {
TextField tf1, tf2;

Detect if Java 1.1 (with event delegation) is available 513


Real's HowTo PDF version

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

Access Cookies from a Java Applet 514


Real's HowTo PDF version

c.add(java.util.Calendar.MONTH, -1);
String expires = "; expires=" + c.getTime().toString();

String s1 = tf1.getText() + expires;


JSObject myBrowser = JSObject.getWindow(this);
JSObject myDocument = (JSObject) myBrowser.getMember("document");
myDocument.setMember("cookie", s1);
}
}

public String getCookie() {


/*
** get all cookies for a document
*/
try {
JSObject myBrowser = (JSObject) JSObject.getWindow(this);
JSObject myDocument = (JSObject) myBrowser.getMember("document");
String myCookie = (String)myDocument.getMember("cookie");
if (myCookie.length() > 0)
return myCookie;
}
catch (Exception e){
e.printStackTrace();
}
return "?";
}

public String getCookie(String name) {


/*
** get a specific cookie by its name, parse the cookie.
** not used in this Applet but can be useful
*/
String myCookie = getCookie();
String search = name + "=";
if (myCookie.length() > 0) {
int offset = myCookie.indexOf(search);
if (offset != -1) {
offset += search.length();
int end = myCookie.indexOf(";", offset);
if (end == -1) end = myCookie.length();
return myCookie.substring(offset,end);
}
else
System.out.println("Did not find cookie: "+name);
}
return "";
}
}

You can try it here.

See this text file with some useful Javascript functions for cookies handling.

Access Cookies from a Java Applet 515


Real's HowTo PDF version

Check this How-to to detect if Cookies are enabled or not.

Set Applet PARAM VALUE from Javascript


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0182.html

PARAM VALUE can't be changed ar run-time but during layout time, javascript "entities" can be used to set
calculated VALUES.

In this How-to, VALUES are coming from a javascript variable, a javascript function and a javascript
expression.

<HTML><HEAD></HEAD><BODY>
<SCRIPT>
var jsVar = "Hello World from jsVar";

function jsFnct() {
return "Hello World from jsFnct";
}

</SCRIPT></HEAD><BODY>
<<APPLET CODE ="MyApplet.class" HEIGHT=100 WIDTH=400>
<PARAM NAME="first" VALUE="&{jsVar};">
<param name="second" value="&{jsFnct()};">
<param name="third"
value="&{'hello world'.toUpperCase() + ' from js Expression'};">
</APPLET>
&LT;/BODY&GT;&LT;/HTML&GT;

For demonstration purpose, the MyApplet class

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

public class MyApplet extends Applet {

public void init() {


add(new Label(getParameter("first")));
add(new Label(getParameter("second")));
add(new Label(getParameter("third")));
}
}

NOTE: Javascript entities are not supported in IE. The workaround is to use the document.write() method to customize the APPLET PARAM during layout
time. See this How-to for an example.

Set Applet PARAM VALUE from Javascript 516


Real's HowTo PDF version

Pass an Array between Java and Javascript


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0183.html

Javascript can read directly a Java Array but the other way don't seem be true. NOTE : Reading a Java
array from Javascript may crash your browser for some unknown reason. So it's safer to use the next
technique!

A safe and simple way is to transform the Array as a big String with a known character used a separator. From
there, it's trivial to do some manipulations to retrieve the array.

In the following example, the first button is used to read directly the Java array. The second button call a Java
method which to transform the array as a string, then the Javascript function split() is used to retrieve the
array. The third button will modify the Java array. A Javascript array is transformed with the function join()
and on the Java-side, a StringTokenizer will do the rest.

[Java applet]

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

public class TestJavaArray extends Applet{


public String javaArray [] =
{ "array 1", "array 2" , "array 3" };

public String [] getJavaArray() {


return javaArray;
}

public String getJavaArrayAsAString() {


// you need more error checking here, of course...
int k;
String s = "";

k = javaArray.length;
s = javaArray[0];
for (int i= 1 ; i < k; i++) {
s += "|" + javaArray[i] ;
}
return s;
}

public void putJavaArray(String arrayAsAString) {


int i = 0;
String s;
StringTokenizer st =
new StringTokenizer(arrayAsAString, "|");

Pass an Array between Java and Javascript 517


Real's HowTo PDF version

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();
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>
&LT;/APPLET&GT;&LT;/BODY&GT;&LT;/HTML&GT;

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

Pass an Array between Java and Javascript 518


Real's HowTo PDF version

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

Pass an Array between Java and Javascript 519


Real's HowTo PDF version

java.lang.reflect.Array.newInstance
(java.lang.Class.forName(type),size)
);
} // else invalid cast
} // else invalid args
}

Interaction without LiveConnect


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0184.html

Java-Javascript 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.

First, define the frameset with an invisible frame.

[SimpleJ2JS.HTML]

Interaction without LiveConnect 520


Real's HowTo PDF version

<FRAMESET ROWS="100%,*">
<FRAME NAME="mainFrame" SRC="visiblepage.html" border=0>
<FRAME NAME="scriptFrame" SRC="invisiblepage.html" border=0>
</FRAMESET>

visiblepage.html contains the Applet and a javascript function. The idea is to type something in a TextField,
press a Button to send a string to a javascript to do an alert() with the TextField content.

[visiblepage.html]

<HTML><HEAD>
<SCRIPT>
function showMessage(s) {
alert(s)
}
</SCRIPT>
</HEAD><BODY><H1>Simple Java to Javascript interaction</H1><P>
<APPLET CODE=SimpleApplet.class
WIDTH=150
HEIGHT=150>
</APPLET></BODY></HTML>

invisiblepage.html contains the function to extract the parameter and call the showMessage() function in the
visible frame.

<HTML><HEAD>
<SCRIPT>
function replace(s, t, u) {
i = s.indexOf(t);
r = "";
if (i == -1) return s;
r += s.substring(0,i) + u;
if ( i + t.length < s.length)
r += replace(s.substring(i + t.length, s.length), t, u);
return r;
}

function getAndSendMessage() {
theMessage = document.location.search.substring(1,255)
if (theMessage.length > 0) {
// replace all '+" by space
theMessage = replace(theMessage, '+', ' ')

window.parent.mainFrame.showMessage(unescape(theMessage))
}
}
</SCRIPT>
</HEAD><BODY onLoad="getAndSendMessage();">
</BODY></HTML>

and finally the Applet (a JDK102 style, since we want to be friendly to older browsers).

Interaction without LiveConnect 521


Real's HowTo PDF version

[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.

Interaction without LiveConnect 522


Real's HowTo PDF version

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>

Interaction without LiveConnect 523


Real's HowTo PDF version

The SimpleApplet2 is TextField which will be used to display the message type in the HTML FORM.

[SimpleApplet2.java]

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

public class SimpleApplet2 extends Applet {


TextField aMessage;

public void init() {


add(new Label("Message from Javascript "));
aMessage = new TextField(20);
add(aMessage);
// put a pointer to this Applet in a static
// variable which can be shared with the InvisibleApplet
SimpleAppletRegistered.sa = this;
}

public void setMessage(String msg) {


aMessage.setText(msg);
}
}

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;

Interaction without LiveConnect 524


Real's HowTo PDF version

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.

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.

Directory listing on the Web server in a Java Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0185.html

There is no way for an Applet to retrieve a directory contents without the help of server side
process(servlet/CGI). But here a way to do it with some help from Javascript.

In a browser, loading a URL with no file specified will return a directory listing under the following
conditions :

1. The directory doesn't contain a default page like index.html, default.htm or default.html.
2. The web server allows directory exploration.

For example, the URL http://www.rgagnon.com/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.

Directory listing on the Web server in a Java Applet 525


Real's HowTo PDF version

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";
}
</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>
&LT;/HTML&GT;

blank.html

<HTML<<HEAD><TITLE&glt;
</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);

Directory listing on the Web server in a Java Applet 526


Real's HowTo PDF version

}
</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>
&LT;/HTML&GT;

Selector.java

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

public class Selector extends Applet


implements ActionListener {
java.awt.List l;
boolean okToDisplay = false;
String targetFrame = "";

public void init() {


setLayout(new BorderLayout());
add(l = new java.awt.List(5), "Center");
l.addActionListener(this);
targetFrame = getParameter("targetFrame");
}

public void actionPerformed(ActionEvent ae) {


if (okToDisplay) {
try {
URL urlToDisplay = new URL(ae.getActionCommand());
getAppletContext().showDocument(urlToDisplay, targetFrame);
}
catch (Exception e) { e.printStackTrace(); }
}
}

public void insertData(String arrayAsAString) {


int i = 0;
String s;
StringTokenizer st =
new StringTokenizer(arrayAsAString, "|");

while(st.hasMoreTokens()){
s = st.nextToken();
l.add(s); // or l.addItem(s);

Directory listing on the Web server in a Java Applet 527


Real's HowTo PDF version

System.out.println(s);
}
okToDisplay = true;
}
}

You can try it here.

NOTE: This How-to is inspired by an article by Martin Webb on http://www.irt.org

Have a Java button close the browser window


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0282.html

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

public class WinClose extends Applet


implements ActionListener{

Button wc = new Button("Close me");

public void init() {


wc.setActionCommand("CLOSE");
wc.addActionListener(this);
add(wc);
}

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

Detect if cookies are enabled


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0303.html

Have a Java button close the browser window 528


Real's HowTo PDF version

The detection is made by trying to write a cookie and reading it back. The value is passed to a Java Applet by
create dynamically the APPLET tag.

[testcookie.html]

<HTML><HEAD></HEAD><BODY>
<SCRIPT>
document.write("<APPLET CODE='MyApplet.class' HEIGHT=100 WIDTH=400>");

// check if cookie are enabled


cookieBackup = document.cookie
document.cookie = "cookie=yep"
cookieOk = document.cookie.indexOf("cookie=yep") > -1
document.cookie = cookieBackup

document.write(" <PARAM NAME='okToCookie' VALUE=" + cookieOk + ">");


document.write("</APPLET>");
</SCRIPT>
</BODY></HTML>

[MyApplet.java]

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

public class MyApplet extends Applet {

public void init() {


add(new Label("Cookie enabled :"));
add(new Label(getParameter("okToCookie")));
}
}

Display a page after all Applets are loaded


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../jsdetails/js-0071.html

Place your page completely in a DIV tag.

Initially the visible attribute is false. When the page is completely loaded, the DIV visibility attribute is set to
true.

<HTML>
<HEAD>
<SCRIPT>
function doIt() {
if (document.all)

Detect if cookies are enabled 529


Real's HowTo PDF version

mypage.style.visibility="visible"
else
document.mypage.visibility="visible"
}

</SCRIPT></HEAD>
<BODY onLoad="doIt();">
<DIV name=mypage style="visibility:hidden" >
...
</DIV>
</BODY>
</HTML>

Detect browser type from an Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-detect-browser-type-from-an-applet.html

Call a Javascript from the Applet

With LiveConnect, we call a javascript to return the "User-Agent".

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

Display a page after all Applets are loaded 530


Real's HowTo PDF version

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/user-agent-utils/ or at this code : http://nerds.palmdrive.net/useragent/code.html to
get the idea.

Get the value from the server-side

When serving the HTML containing the Applet, you add the User-Agent as parameter for the Applet.

In a JSP/EL

<applet ... >


<param ... >
<param name="userAgent" value="${header['user-agent']}" />
</applet>

and in the Applet

String userAgent = getParameter("userAgent");

and parse the returned value...

Detect browser type from an Applet 531


Real's HowTo PDF version

Written and compiled Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Detect browser type from an Applet 532


Servlet/JSP
java-jsp

Read me
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0379.html

You may to take a look to these related How-to's in the EAServer/Jaguar section.

Get servlet parameters


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0357.html

<HTML>
<HEAD></HEAD>
<BODY>
<FORM METHOD=POST ACTION="/servlet/MyServlet">
value : <INPUT TYPE="TEXT" NAME="someValue">
</FORM>
</BODY>
</HTML>

import javax.servlet.*;
import javax.servlet.http.*;

public class MyServlet extends HttpServlet {


public void doPost(HttpServletRequest req, HttpServletResponse res) {
// note : if "someValue" is missing a null is returned
String valuePassed = req.getParameter("someValue");
res.setContentType("text/html");

java.io.PrintWriter out = res.getWriter();


out.println("<html><head></head><body>");
out.println("the value is : " + valuePassed);
out.println("</body></html>");
}

public void doGet(HttpServletRequest req, HttpServletResponse res) {


doPost(req, res);
}

Servlet/JSP 533
Real's HowTo PDF version

Servlet with no args


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0341.html

Servlet 2.3

int i = req.getParameterMap().size();
if (i = 0) {
// no arguments
}
else {
Enumeration paramNames = req.getParameterNames();
while(paramNames.hasMoreElements()) {
String parm = (String)paramNames.nextElement();
// do something with this parm
}
}

Previous version of the Servlet API

protected void doGet


(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
response.setContentType( "text/html" );
out.println("<HTML>");
if (!request.getParameterNames().hasMoreElements()) {
// no arguments
out.println("<HEAD><TITLE>MyServlet (no args)</TITLE></HEAD>");
out.println("<BODY>");
out.println("<H1>MyServlet</H1>");
out.println("<FORM METHOD='GET' ACTION='Servlet1'>");
out.println(" Subject<INPUT TYPE=INPUT NAME=subject>");
out.println(" Recipients<INPUT TYPE=INPUT NAME=to>");
out.println(" Message<INPUT TYPE=INPUT NAME=message>");
out.println(" <INPUT TYPE=SUBMIT VALUE='Ok'>");
out.println(" </FORM>");
}
else {
out.println("<HEAD><TITLE>MyServlet (with args)</TITLE></HEAD>");
out.println("<BODY>");
out.println("<H1>Servlet</H1>");
java.util.Enumeration paramNames = request.getParameterNames();
while(paramNames.hasMoreElements()) {
String parm = (String)paramNames.nextElement();
out.println(parm + " = " + request.getParameter(parm) + "<BR>");
}

Get servlet parameters 534


Real's HowTo PDF version

out.println("</BODY></HTML>");
}
}

Set a Cookie from a servlet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0358.html

import javax.servlet.*;
import javax.servlet.http.*;

public class MyServlet extends HttpServlet {


public void doPost(HttpServletRequest req, HttpServletResponse res) {
res.addCookie(new Cookie("mycookie_name", "mycookie_value"));
}

public void doGet(HttpServletRequest req, HttpServletResponse res) {


doPost(req, res);
}

Read a Cookie from a servlet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0359.html

import javax.servlet.*;
import javax.servlet.http.*;

public class MyServlet extends HttpServlet {


public void doPost
(HttpServletRequest req, HttpServletResponse res) {
Cookie[] theCookies = request.getCookies();
if (theCookies != null) {
java.io.PrintWriter out = res.getWriter();
for (int i =0; i<cookies.length; i++) {
Cookie aCookie = theCookies[i];
out.println
("Name : " + aCookie.getName()
+ " Value: " + aCookie.getValue());
}
}
}

Servlet with no args 535


Real's HowTo PDF version

public void doGet(HttpServletRequest req, HttpServletResponse res) {


doPost(req, res);
}

Delete a Cookie from a servlet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0360.html

import javax.servlet.*;
import javax.servlet.http.*;

public class MyServlet extends HttpServlet {


public void doPost(HttpServletRequest req, HttpServletResponse res) {

Cookie cookie = new Cookie ("myCookie", "theCookieValue");

// Expire in five minutes (5 * 60)


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

Ask a password from a Servlet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0342.html

public void askPassword(HttpServletResponse response) {


response.setStatus(response.SC_UNAUTHORIZED);

Read a Cookie from a servlet 536


Real's HowTo PDF version

response.setHeader("WWW-Authenticate",
"BASIC realm=\"protected-area\"");
}

then the browser will popup a dialog for username/password

Talk to a Servlet/JSP from an Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0082.html

From the client point of view, there is no difference talking to CGI or Servlet. There is two ways to send a
request to a CGI. The GET method contains encoded parameters in the URL. A typical URL talking to CGI
using the GET method would be:

new URL("http://www.server.com/cgi-bin/acgi.pl?name=real&site=java+howto");

Here we calling a script called aCGI.pl (a PERL script) passing the parameters name and site. Parameters are
encoded, spaces are changed to "+" and special character to hexadecimal using a 3-letter escape sequence.
Each parameter is delimited by the character "&". Habitually the encoding is done through the static method
encode of the java.net.URLencoder class.

String theCGI = "http://www.server.com/cgi-bin/aCGI.pl?";


String encoded = "name=" + URLencoder.encode("Real Gagnon");
URL cgiurl = new URL(thecgi + encoded);

Once the URL is constructed, you call the CGI using the showDocument method (Applet).

getAppletContext().showDocument(cgiurl);

The CGI will process the result and produce a page to be displayed.

The POST method allows the programmer to manipulate the data received from the CGI. First a connection is
made to the CGI, an OutputStream is open to send the parameters (if any). Then InputStream is created to
receive the result.

String theCGI = "http://www.server.com/cgi-bin/aCGI.pl";


String encoded = "name=" + URLencoder.encode("Real Gagnon");
URL CGIurl = new URL(theCGI);

URLConnection c = CGIurl.openConnection();
c.setDoOutput(true);
c.setUseCaches(false);
c.setRequestProperty("content-type","application/x-www-form-urlencoded");
DataOutputStream out = new DataOutputStream(c.getOutputStream());
out.writeBytes(encoded);
out.flush(); out.close();

Ask a password from a Servlet 537


Real's HowTo PDF version

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.

Test for Cookies support


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0374.html

import javax.servlet.*;
import javax.servlet.http.*;

public class Test4Cookies extends HttpServlet {

private static final Cookie cookie = new Cookie( "hello" , "world" );


private static final String paramName = "foo";
private static final String successURI = "/success.htm";
private static final String failureURI = "/failure.htm";

public void doPost(HttpServletRequest req, HttpServletResponse res) {


if ( req.getParameter( paramName ) == null ) {
res.addCookie( cookie );
res.sendRedirect(req.getRequestURI() +"?"+ paramName +"=bar" );
}
else {
res.sendRedirect
(( req.getCookies().length == 0 ) ? failureURI : successURI
)
}

public void doGet(HttpServletRequest req, HttpServletResponse res) {


doPost(req, res);
}
}

Talk to a Servlet/JSP from an Applet 538


Real's HowTo PDF version

Display ResultSet data in an HTML Table in Servlet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0378.html

private int dumpData(java.sql.ResultSet rs, java.io.PrintWriter out)


throws Exception {
int rowCount = 0;

out.println("<P ALIGN='center'><TABLE BORDER=1>");


ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
// table header
out.println("<TR>");
for (int i = 0; i < columnCount; i++) {
out.println("<TH>" + rsmd.getColumnLabel(i + 1) + "</TH>");
}
out.println("</TR>");
// the data
while (rs.next()) {
rowCount++;
out.println("<TR>");
for (int i = 0; i < columnCount; i++) {
out.println("<TD>" + rs.getString(i + 1) + "</TD>");
}
out.println("</TR>");
}
out.println("</TABLE></P>");
return rowCount;
}

Specify the filename to be used for a file sent by a Servlet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0387.html

Say that your servlet called ""/servlet/GetFile" send back a file to a client request. That file needs to be saved
by the client. If you do nothing, the browser will suggest "GetFile" as the filename.

To specify the correct filename

String filename = "abc.dat" ;


File textFile = new File(filename);
response.setHeader("Content-length",Integer.toString(textFile.length()));
response.setHeader("Content-type","application/octetstream");
response.setHeader("Content-disposition","inline; filename=" + filename );

Display ResultSet data in an HTML Table in Servlet 539


Real's HowTo PDF version

// open the file and write it in the OutputStream

NOTE: For PDF output, see this HowTo

Pass information to another servlet/jsp


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0401.html

You set attributes on your request object and then forward the request object to the other servlet/jsp.

For a simple string

request.setAttribute("foo", "Real's HowTo");

A parameter received by the first servlet to the second one

String requestVar = request.getParameter("sitename");


request.setAttribute("foo", requestVar);

A Bean

MyBean myBean = new MyBean();


myBean.setFooProperty("Real's HowTo");
request.setAttribute("foo", myBean);

Then you forward the request

RequestDispatcher dispatch = request.getRequestDispatcher("next.jsp");


dispatch.forward(request, response);

Handle PDF output


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0404.html

• Set the content-type of the response to "application/pdf", ex.


response.setContentType("application/pdf");
• Add a dummy parameter on the end of the url, like:
http://x.y.z/DoGenCompStmt?filename=dummy.pdf
because IE ignores content-types, so you need to give it a hint, and the ".pdf" extension is an easy
way.

Specify the filename to be used for a file sent by a Servlet 540


Real's HowTo PDF version

• Set the "content-length" on the response, otherwise the Acrobat Reader plugin may not work properly,
ex. response.setContentLength(bos.size());
• An additional thing that seems to help some IE browsers is to also have :
response.setHeader("Content-Disposition", "inline;filename=somepdf.pdf");

Detect if a connection is secured


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0415.html

Use the servlet request's isSecure() or getAuthType() methods. Or you look at these HTTP headers :
CERT_KEYSIZE , CERT_KEYSIZE, HTTPS_KEYSIZE

Note: for a javascript solution see this HowTo

In a Servlet, check if Form Field is present


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0443.html

public isDefined(HttpServletRequest req, String fieldNameToSearchFor) {


return req.getParameterMap().containsKey(fieldNameToSearchFor);
}

Get the root dir of a web app


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0519.html

In a JSP

String path = application.getRealPath("/");

In a Servlet

String path = getServletContext.getRealPath("/");

Get Client IP from JSP


Current version of this HowTo :

Handle PDF output 541


Real's HowTo PDF version

http://www.rgagnon.com/javadetails/../javadetails/java-0363.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("x-forwarded-for") );
%>

Binary output from a JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0366.html

You can't.

From JSP, only character stream should be used.

JSP pages were designed for *text* output. The "out" object is a Writer, which means it will play games with
text encoding.

For binary output, like PDF or dynamically generated GIF, it's a better idea to use a servlet.

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

Get Client IP from JSP 542


Real's HowTo PDF version

o.flush();
o.close();// *important* to ensure no more jsp output
return;
%&GT;

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 jsp-config section your web.xml

<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<trim-directive-whitespaces>true</trim-directive-whitespaces>
</jsp-property-group>
</jsp-config>

If you really have a required space in the generated JSP then you need use the HTML non-breaking space
entity : &nbsp; .

Use a connection cache from JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0380.html

Jaguar provides a very useful cache mechanism to speed up database requests. You can have ODBC, JDBC or
Oracle cached connections.

NOTE: Java component can't use cached ODBC connection, you need to use a cached JDBC connection. If there is no JDBC driver available, it's still possible
to use the ODBC-JDBC provided by Sun. But performance of such a bridge is poor and the reliability is not good in a multi-threaded environment.

To define a cache using ODBC-JDBC (bridge) connection, follow these steps:

1. Define a regular System DSN (through the ODBC Administration panel)


2. In jaguar, you define the cache :
1. General Tab : Server name = jdbc:odbc:YourSystemDSNName with user/pwd
2. Driver Tab : DLL or class name = sun.jdbc.odbc.JdbcOdbcDriver with JDBC radio button
selected
3. Cache Tab : checkbox cache-by-name checked

<%@page contentType="text/html"%>
<html>

Binary output from a JSP 543


Real's HowTo PDF version

<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 hard-coding the cache name into your java component, make the name available through a Property
(of the Environment) of the Web application. This way your components are more flexible and you are using
the "J2EE way" to make a connection. In this example, myconnection contains the cache name to be used.

javax.naming.InitialContext ctx = new javax.naming.InitialContext();


javax.sql.DataSource ds = (javax.sql.DataSource)
ctx.lookup("java:comp/env/jdbc/myconnection");
java.sql.Connection con = ds.getConnection();
java.sql.PreparedStatement stmt = con.prepareStatement(sql);
java.sql.ResultSet rs = stmt.executeQuery();

while (rs.next()) {
//do something
}

Use a connection cache from JSP 544


Real's HowTo PDF version

Read a web application property


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0381.html

Web Application properties are defined in the WEB-INF/web.xml deployment descriptor (in between the
<webapp> </webapp> tag)

<env-entry>
<env-entry-name>docPath</env-entry-name>
<env-entry-value>c:/doc/doc1</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry>

<env-entry>
<env-entry-name>docUser</env-entry-name>
<env-entry-value>net1</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry>

Then from your JSP or Servlet,

Context env = (Context) new InitialContext().lookup("java:comp/env");


String docBase = (String) env.lookup("docPath");
String docBaseUser = (String) env.lookup("docUser");

Use EJB from JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0396.html

EJB with constructor with no parameter

<jsp:useBean id="myBean" scope="session" class="com.company.MyBean"/>

EJB with constructor with parameters

<%
com.company.MyBean bean=new com.company.MyBean(1, 2, 3, 4);
session.putAttribute("myBean", bean);
%>

Read a web application property 545


Real's HowTo PDF version

Define a method in a JSP page


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0410.html

<%!
public String sayHello(){
return "Hello";
}
%>

<%= sayHello() %>

Precompile JSP page


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0414.html

Some JSP containers (as per section 8.4.2 of the JSP 1.2 specification) support the capability of precompiling
a JSP page.

To precompile a JSP page, access the page with a query string of ?jsp_precompile

http://hostname.com/mywebapp/mypage.jsp?jsp_precompile

The JSP page will not be executed. If the container supports precompilation, the JSP page will be compiled if
necessary.

Here a JSP page that will scan the current directory (and subdirectories) to precompile all JSP found.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


<%@ page import="javax.servlet.*"%>
<%@ page import="javax.servlet.http.*,javax.servlet.jsp.*"%>
<%@ page import="java.util.Set,java.util.Iterator,java.io.IOException"%>

<%! private void compileAllJsps


(PageContext pageContext, JspWriter out,
HttpServletRequest request,HttpServletResponse response,
String uripath)
throws IOException, ServletException {

Set set = pageContext.getServletContext().getResourcePaths(uripath);


for (Iterator iter = set.iterator(); iter.hasNext();) {
String uri = (String) iter.next();

Define a method in a JSP page 546


Real's HowTo PDF version

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.

Get a list of directories from JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0417.html

<h1>Directories</h1>
<ul>
<%
String root="c:/Repository/WebApplication/mydocs/javadoc/";
java.io.File file;
java.io.File dir = new java.io.File(root);

String[] list = dir.list();

if (list.length > 0) {

Precompile JSP page 547


Real's HowTo PDF version

for (int i = 0; i < list.length; i++) {


file = new java.io.File(root + list[i]);
if (file.isDirectory()) {
%>
<li><a href="javadoc/<%=list[i]%>" target="_top"><%=list[i]%></a><br>
<%
}
}
}
%>
</ul>

Use and share a class in JSP pages


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0508.html

I have a class

public class Hello {


public String say() {
return "Hello";
}
}

and I need to use it in many JSP pages using

<%= say() %>

They are many to achieve that goal :

• Create a Java class with the method in it, compile it, and deploy the resulting .class file(s) in your webapp's
WEB-INF/class directory.
<%
Hello h = new Hello();
out.print(h.say());
%>
• Create a JAR file containing the .class file(s) and deploy the resulting JAR file via your webapp's
WEB-INF/lib directory.
<%
Hello h = new Hello();
out.print(h.say());
%>
• Create a tag library for it, deploy it via the webapp's WEB-INF/tld directory.

TAG source code

Get a list of directories from JSP 548


Real's HowTo PDF version

TAG source code :

package test;

import java.io.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

public class HelloTag extends TagSupport {


public int doStartTag() throws JspException
{
try {
pageContext.getOut().println("Hello");
} catch (IOException e) {
}

return SKIP_BODY;
}
}

the resulting class should go in the WEB-INF/class directory.

TLD configuration (in the WEB-INF/tlds as hello.tld)

<taglib>
<tag>
<name>hello</name>
<tagclass>test.HelloTag</tagclass>
</tag>
</taglib>

and to use the tag

<%@ taglib prefix="ht" uri="WEB-INF/tlds/hello.tld" %>


...
<ht:hello/>
• Create the desired method at the top of the page and copy it from page to page
<%!
public static String say() {
return "Hello";
}
%>
• Create an "include file" (say hello.inc), place the method noted above in it, and include it at the top of each
JSP page
<%@ include file="hello.inc" %>

Get the root dir of a web app


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0519.html

Use and share a class in JSP pages 549


Real's HowTo PDF version

In a JSP

String path = application.getRealPath("/");

In a Servlet

String path = getServletContext.getRealPath("/");

Launch an applet from a JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0534.html

The jsp:plugin tag will generate the right html code to load your Applet.

<jsp:plugin type="applet"
code="TestApplet.class"
width="500"
height="300">

<jsp:params>
<jsp:param name="message" value="Hello, world"/>
<jsp:param name="action" value="<%=AppletAction%>"/>
</jsp:params>

<jsp:fallback>
<p> unable to start plugin </p>
</jsp:fallback>
</jsp:plugin>

Prevent caching of a JSP output


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0590.html

You will need to set the appropriate HTTP header attributes.

<%
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
response.setDateHeader ("Expires", -1);
%>

However, cache handling is tricky with IE brower.

Get the root dir of a web app 550


Real's HowTo PDF version

See http://support.microsoft.com/kb/q222064/.

By adding a second HEAD is supposed to solve the problem!

<%
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
response.setDateHeader ("Expires", -1);
%>
<HTML>
<HEAD>
</HEAD>
<BODY>
my page body

</BODY>
<HEAD>
<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
<META HTTP-EQUIV="Expires" CONTENT="-1">
</HEAD>
</HTML>

NOTE: Pragma: no-cache prevents caching only when used over a secure connection, Expires: -1 should do
the job over unsecure conection.

See also this HowTo and this one.

Launch an external program, capture its output and display it


in a JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0648.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()));

Prevent caching of a JSP output 551


Real's HowTo PDF version

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


out.println(line);
}
input.close();
}
catch (Exception err) {
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);

Launch an external program, capture its output and display itin a JSP 552
Real's HowTo PDF version

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

Call another EJB


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0384.html

InitialContext ctx = new InitialContext();


Object objref = ctx.lookup("MyPackage/MyEJB");
MyEJBHome home = (MyEJBHome)
PortableRemoteObject.narrow(objref, MyEJBHome.class);
return (MyEJB) home.create();

Keep java files generated from JSP (BEA WLS)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0446.html

Set the 'keepgenerated' parameter in weblogic.xml to 'true'

<jsp-descriptor>
<jsp-param>
<param-name>keepgenerated</param-name>
<param-value>true</param-value>
</jsp-param>
<jsp-param>
<param-name>working-dir</param-name>
<param-value>c:/bea10/user_projects/domains/mydomain/tmp</param-value>
</jsp-param>
</jsp-descriptor>

Thanks to jimbo for the tip!

Get the server version (BEA WLS)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0447.html

Call another EJB 553


Real's HowTo PDF version

<%@page import = "weblogic.common.internal.VersionInfo"%>


...
<%VersionInfo serverVersion = VersionInfo.theOne();%>
...
&LT;%=serverVersion.getImplementationVersion()%&GT;

or from the command line

java -cp weblogic.jar weblogic.version

Thanks to Frederic Close for the tip!

Quickly create a Web application with BEA WLS


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0449.html

To create a web application without an EAR or WAR, follow these steps :

1. Open a Shell window in %BEA%\user_projects\domains\[mydomain]\applications


2. Run this script : ..\setenv.cmd
3. Type this command : md testapp
4. Type this command : md testapp\WEB-INF
5. Run this program : java weblogic.marathon.ddinit.WebInit testapp

and that's all.

To configure your new application, run this program java weblogic.marathon.Main testapp

Nicely display WEB.XML informations


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0451.html

A web.xml file contains informations about a web application hosted by a application server. While it's
possible to consult the data using a regular text editor, it maybe easier to use a special stylesheet to nicely
format the data for easy browsing.

I found a nice generic stylesheet on the Web and adapted it a little bit for that purpose. Here the modified
xsl file, the css file, a sample web.xml.

See the sample output if your browser supports XML/XSL transformation.

Attach the xsl to the xml by adding this line to the xml file :

Get the server version (BEA WLS) 554


Real's HowTo PDF version

<?xml version="1.0" encoding="UTF-8"?>


<?xml-stylesheet type="text/xsl" href="tree-view.xsl"?>
...

or do the transformation in Java, for a hint see this How-to.

Here an ASP page (yeah I know...) which accepts as a parameter an XML filename and transforms the
passed filename using the XSL. As an added bonus, the original XML filename is displayed (you will need
this XSL).
<META http-equiv="Content-Type" content="text/html; charset=ISO8859-1">
<%@ LANGUAGE="JScript" %>
<%
Response.buffer = true;
var xmlfile;
var oXML;
var oXSL;
var oXSLTemplate;
var oXSLProcessor;
var SrcXSL;
var SrcXML;

// get the PARAM=??? (assumes you have used GET request method!)...
// assume something like http://.../docxml.asp?xmlfile=myxml.xml
xmlfile = '' + Request.QueryString('xmlfile');

// get the source file (XML and XSL) paths


SrcXML = Server.MapPath(xmlfile);
SrcXSL = Server.MapPath('xmldoc/tree-view2.xsl');

// create documents for the XML and XSL...


oXML = Server.CreateObject('Msxml2.DOMDocument');
oXSL = Server.CreateObject('Msxml2.FreeThreadedDOMDocument');

// load the XML and XSL into your documents...


// we don't want to waste time validating the file
oXSL.load(SrcXSL);
oXML.validateOnParse = false ;
oXML.async = false ;
oXML.resolveExternals = false ;

oXML.load(SrcXML);

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

Nicely display WEB.XML informations 555


Real's HowTo PDF version

try {
oXSLProcessor.transform ;
Response.write(oXSLProcessor.output);
}
catch (e) {
Response.write
('The file ' +e.url + ' is not valid. Reason: ' + e.reason );
}

%&GT;

Reverse the CLASSLOADER order (BEA)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0551.html

By default, Weblogic loads a class by asking the parent classloader to load the required class. This can be a
problem, if you have a JAR version in the server LIB directory and your web app requires an another
version.

ref : WebLogic Server Application Classloader Overview

To make sure that your web app will use the JAR located in its WEB-INF\LIB, create a file called
weblogic.xml in the WEB-INF directory with the content :

<!DOCTYPE weblogic-web-app PUBLIC


"-//BEA Systems, Inc.//DTD Web Application 8.1//EN"
"http://www.bea.com/servers/wls810/dtd/weblogic810-web-jar.dtd">

<weblogic-web-app>
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
</weblogic-web-app>

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


prefer-application-packages descriptor element to the weblogic-application.xml

The following example specifies that org.apache.log4j.* is loaded from the application, not the system
classloader:

Reverse the CLASSLOADER order (BEA) 556


Real's HowTo PDF version

<prefer-application-packages>
<package-name>org.apache.log4j.*</package-name>
</prefer-application-packages>

ref : http://download.oracle.com/docs/cd/E11035_01/wls100/programming/classloading.html#wp1097187

Detect change in JSP and recompile (BEA)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0562.html

By default, if you deployed an application in exploded mode, BEA WLS doesn't recompile a modified JSP.
You change this behaviour by adding this directive in a weblogic.xml configuration file.

<jsp-descriptor>
<jsp-param>
<param-name>page-check-seconds</param-name>
<param-value>60</param-value>
</jsp-param>
</jsp-descriptor>

page-check-seconds sets the interval, in seconds, at which WLS checks to see if JSP files have changed and
need recompiling. Dependencies are also checked and recursively reloaded if changed.

If set to 0, pages are checked on every request. If set to -1, page checking and recompiling is disabled.

Obtain a remote connection to a DataSource or EJB (Weblogic)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0664.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 java.sql.*;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import javax.sql.DataSource;

public class RemoteConnection {


private RemoteConnection() { }

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


Properties env = new Properties();
String datasourceName = "mydatasourcename";

Detect change in JSP and recompile (BEA) 557


Real's HowTo PDF version

env.put("java.naming.factory.initial",
"weblogic.jndi.WLInitialContextFactory");
env.put("java.naming.provider.url",
"t3://xxxxxxxx-xxxxx.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 java.util.Properties;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import 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://xxxxxxxx-xxxxx.xxx.xxxxx:7101");
InitialContext ctx = new InitialContext(env);
Object obj = ctx.lookup("common/MyEJB");

Obtain a remote connection to a DataSource or EJB (Weblogic) 558


Real's HowTo PDF version

MyEJBHome home = (((MyEJBHome) PortableRemoteObject


.narrow(obj, MyEJBHome.class)));
MyEJB myEJB = home.create();

System.out.println(myEJB.doit());
}
}

Written and compiled Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Obtain a remote connection to a DataSource or EJB (Weblogic) 559


Language
java-language

*Read me*
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0290.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.

Stack Overflow
A site where you can ask question (not restricted to Java), really innovative in the way it works. Participants
are really cool.

Obtain from where a Class is loaded


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0300.html

This HowTo detects where the class is coming from.

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


}

Language 560
Real's HowTo PDF version

class MyClass {
MyClass() {
System.out.println
(this.getClass().getName() + " is loaded from " +
this.getClass().getProtectionDomain().getCodeSource().getLocation());
}
}

The output

C:/temp>java LoadingFromWhere
LoadingFromWhere is loaded from file:/C:/temp/
MyClass is loaded from file:/C:/temp/

If running from a Jar

C:/temp>java -jar testing.jar


LoadingFromWhere is loaded from file:/C:/temp/testing.jar
MyClass is loaded from file:/C:/temp/testing.jar

Other technique

package com.rgagnon;

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

This technique returns the package too, If the class is in the com.rgagnon package then the output is

C:/temp> java FromWhere


This class (FromWhere) is located at : file:/C:/temp/com/rgagnon

It doesn't work if running from a Jar, a null value is returned.

See these related HowTo's :


• Get the "root" of an application
• Determine if running from JAR

Get the class name in a static method


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0402.html

Obtain from where a Class is loaded 561


Real's HowTo PDF version

The hard-coded 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
*/
}
}

The dynamic way

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(); // can be .getSimpleName() to get
// the class name without the package
}
}

/*
output :
I'm in com.rgagnon.howto.ClassFromStatic class
*/

Get the current method name


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0420.html

Get the class name in a static method 562


Real's HowTo PDF version

JDK1.4+

Get the current method

public class MyTest {


public static void main(String args[]) {
new MyTest().doit();
}
public void doit() {
System.out.println
(new Exception().getStackTrace()[0].getMethodName()); // output :doit
}
}

JDK1.5+

While the above snippet is not bad, it is expensive since we need to create an Exception each time we needa
trace.

With JDK1.5, a better technique is available to get the current method.

public class Test {


public static void main(String args[]) {
trace(Thread.currentThread().getStackTrace()); // output :main
new Test().doit();
trace(Thread.currentThread().getStackTrace()); // output :main
}
public void doit() {
trace(Thread.currentThread().getStackTrace()); // output :doit
doitagain();
}
public void doitagain() {
trace(Thread.currentThread().getStackTrace()); // output : doitagain
}

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

Now we know how to get the current method. If we need the calling instead instead :

Get the current method name 563


Real's HowTo PDF version

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


• Trace the execution.

Call a method dynamically


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0031.html

import java.lang.reflect.*;
import java.io.*;

public class TestReflect {

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


String aClass;
String aMethod;
// we assume that called methods have no argument
Class params[] = {};
Object paramsObj[] = {};

while (true) {
aClass = lineInput("\nClass : ");
aMethod = lineInput("Method: ");
// get the Class
Class thisClass = Class.forName(aClass);
// get an instance
Object iClass = thisClass.newInstance();
// get the method
Method thisMethod = thisClass.getDeclaredMethod(aMethod, params);
// call the method
System.out.println
(thisMethod.invoke(iClass, paramsObj).toString());
}
/* Output examples:
Class : Class1
Method: class1Method2
### Class 1, Method2 ###

Class : java.util.Date
Method: toString

Call a method dynamically 564


Real's HowTo PDF version

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

Call a method dynamically 565


Real's HowTo PDF version

class Class1 {
public void say( String s1, String s2) {
System.out.println(s1 + " " + s2);
}
}

Detect if a package is available


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0422.html

public class ClassUtils {

private ClassUtils() {}

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 ClassUtils.isAvailable("javax.media.j3d.View");
}

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

Detect if a package is available 566


Real's HowTo PDF version

}
}

Create an Object from a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0351.html

In this HowTo, we instantiate an object from its classname and pass a parameter to the constructor. And
then, we are 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);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

Create an Object from a String 567


Real's HowTo PDF version

Get a variable value from the variable name


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0038.html

import java.lang.reflect.Field;

public class ReflectUtils {

private ReflectUtils (){ }

@SuppressWarnings("rawtypes")
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);
}

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

class TestClass {
public double firstValue = 3.1416;
public int secondValue = 42;
public String thirdValue = "Hello world";
}

Get a variable value from the variable name 568


Real's HowTo PDF version

Make methods that have unspecified number of parameters


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0289.html

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

With JDK1.5+, a better approach is use VARARGS parameters.

public class TestIt {


public static void main(String ... args) {
for(String arg:args) {
System.out.println(arg);
}
}
/*
output :
>java TestIt 1 2 3 how-to
1
2
3
how-to
*/
}

The ellipsis … means that you can pass 0 or more parameters. If you prefer to force 1 parameter or more
then you can add 1 parameter followed by the VARARGS parameter to the signature.

public class Misc {


public static void main(String args[]){
System.out.println(Misc.sum(30,3,3,6)); // output 42
}

public static int sum(int num, int... nums) {


int total = num;
for(int n: nums) total += n;
return total;

Make methods that have unspecified number of parameters 569


Real's HowTo PDF version

}
}

The advantage is if you try to call the method with no parameter then the call will fail at compile time and
not runtime.

System.out.println(Misc.sum()); // Fails with


// "The method sum(int, int...) in the type Misc is not appli

Create a java source dynamically, compile and call


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0039.html

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 javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import 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);

Create a java source dynamically, compile and call 570


Real's HowTo PDF version

fileManager.setLocation(StandardLocation.CLASS_OUTPUT,
Arrays.asList(new File("/temp")));
// Compile the file
compiler.getTask(null,
fileManager,
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).

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

Create a java source dynamically, compile and call 571


Real's HowTo PDF version

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


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

Create a java source dynamically, compile and call 572


Real's HowTo PDF version

Launch an application from another application


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0394.html

While you can exec("java myanotherapp"), it is more appropriate to instanciate and called the main method
of the other application.

For example, take this simple application :

public class Program2 {


public static void main(String arg[]) {
System.out.println("Hello from Program2");
}
}

To call the above application from another

public class Program1a {


public static void main(String arg[]) {
System.out.println("Hello from Program1a");
new Thread(){
public void run() {
Program2.main(new String[]{});}
}.start();
}

The above example is used when the class is hard-coded.

The dynamic version is little more tricky.

public class Program1b {


public static void main(String arg[]) {
System.out.println("Hello from Program1b");
new Program1b().execute("Program2");
}

public void execute(String name) {


Class params[] = {String[].class};
// if you need parameters
// String[] args = new String[] { "Hello", "world" };
// Class params[] = new Class[] { args.getClass() });
try {
Class.forName(name).
getDeclaredMethod("main", params).
invoke(null, new Object[] {new String[] {}});
}

Launch an application from another application 573


Real's HowTo PDF version

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
Hello from Program1a

Access the enclosing class from an inner class


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0037.html

public class TestIt {


public static void main(String a[]){
new TestIt().doit();
/*

Access the enclosing class from an inner class 574


Real's HowTo PDF version

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 :
Hello world!
*/
}

public void doit() {


new InnerClass().sayHello();
}

public void enclosingClassMethod(){


System.out.println("Hello world!");
}

class InnerClass {
public void sayHello() {
testItClass.enclosingClassMethod();
}
}
}

Access inner class from outside


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0425.html

Access inner class from outside 575


Real's HowTo PDF version

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

Use globally defined constants


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0040.html

Via a class
This technique is useful for constants defined on a corporate level. They are very generic by nature. The
CONSTANT class is included in the classpath.

public class CONSTANT {


private CONSTANT() {}
public static final integer SUCCESS = 1;
public static final integer FAILURE = -1;
public static final integer NOTFOUND = 0;
}

Since the members of the class are defined as "static", there is no need to instantiate the class (That's why
the consructor is private). 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

Use globally defined constants 576


Real's HowTo PDF version

specific application for example. An application-level class needs to implement the interface to be able to
see the constant definitions.

public interface APPCONSTANT {


public static final String APPNAME = "The Super APP";
public static final String APPVERSION = "version 1.0";
public static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
}

then to use a constant, simply implement the interface

public class TheAppFrame extends Frame implements APPCONSTANT {

TheAppFrame {
...
setTitle(APPNAME);
...
}
...
}

NOTE : This is not considered as good practice (depending on who you are talking to!) to use an interface
this way.

NOTE: By convention, a constant name is always in CAPITALS.

JDK1.5

JDK1.5 import statement can be used to import only static member from a class.

import static java.lang.Math.PI;


import static java.lang.Math.abs;

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

Serialize an Object
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0042.html

Use globally defined constants 577


Real's HowTo PDF version

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 serialize an ArrayList to a file and we reload it.

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;

public class SerializeDemo {

@SuppressWarnings("unchecked")
public static void main(String args[]) throws IOException, ClassNotFoundException {
ArrayList <String> arraySerialized = new ArrayList<String>();
arraySerialized.add("element 1");
arraySerialized.add("element 2");
arraySerialized.add("element 3");
arraySerialized.add("element 4");
arraySerialized.add("element 5");
System.out.println("ArrayList to be serialized : " + arraySerialized );
System.out.println("serializing the array");
ObjectOutputStream oos = null;
try {
FileOutputStream fout = new FileOutputStream("c:\\temp\\thearraylist.dat");
oos = new ObjectOutputStream(fout);
oos.writeObject(arraySerialized);
}
finally {
if (oos!=null) oos.close();
}

// deserialize the ArrayList


ArrayList <String> arrayUnserialized = new ArrayList<String>();
System.out.println("unserializing the array");
ObjectInputStream ois = null;
try {
FileInputStream fin = new FileInputStream("c:\\temp\\thearraylist.dat");
ois = new ObjectInputStream(fin);
arrayUnserialized = (ArrayList) ois.readObject();
ois.close();
}
finally {

Serialize an Object 578


Real's HowTo PDF version

if (ois!=null) ois.close();
}
System.out.println("ArrayList unserialized : " + arrayUnserialized);
}
}

Note : See this How-to to serialize using XML format.

If you need to serialize and manipulate huge objects, take a look at this open-source project.

joafip( java data object persistence in file ) at http://joafip.sourceforge.net.

Serialize an Object over a Socket


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0043.html

From the client side, you open a Socket and then

oos = new ObjectOutputStream(socket.getOutputStream());


oos.writeObject(someObject);

On the server side, you use the ObjectInputStream.readObject() method.

NOTE:
If the OutputStream is kept open and you modify your object and resend it, you will not see a change on the
server side. That's because Java keeps objects sent in an internal cache and the old version will be taken in
account instead of the new one. The fix is to do an ObjectOutputStream.reset() before re-sending the object
or open a new connection each time.

Easily remove my debugging code


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0130.html

Unlike a C/C++ compiler, there is no Java compiler directive to exclude certain source code parts from
compilation. By making the release version of a class smaller, the loading process will be a little bit 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.

Serialize an Object over a Socket 579


Real's HowTo PDF version

The technique is simple. In the development environment, you have a class called Debug.

public class Debug {


private Debug() {}
public static final boolean RELEASE = true;
}

In your source, when you need some debugging codes, you included them in a if statement like

if (Debug.RELEASE) {
System.out.println("The value of i is " + i);
}

During compilation, since Debug.RELEASE is always true, the code will be present.

In the production environment, the Debug class looks like this:

public class Debug {


private 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.

Have a Singleton
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0355.html

A singleton is a class that can be instantiated only one time in a JVM. Repeated calls always return the
same instance.

public class OnlyOne{


private static OnlyOne one = new OnlyOne();

private OnlyOne(){}

public static OnlyOne getInstance() { return one; }


}

To use it

OnlyOne myOne = OnlyOne.getInstance();

Easily remove my debugging code 580


Real's HowTo PDF version

Multiple expressions in for loops


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0316.html

Simply use a "," between each expression.

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

/*
output :
i = 0 j= 0
i = 1 j= -1
i = 2 j= -2
i = 3 j= -3
i = 4 j= -4
i = 5 j= -5
i = 6 j= -6
i = 7 j= -7
i = 8 j= -8
i = 9 j= -9
*/

Handle the List conflict (java.awt.List/java.util.List)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0372.html

The List interface is declared in the java.util package and the List class is in the java.awt package. So if
both import are defined in your source you won't be able to compile properly because this will cause a
name conflict. The solution is to fully qualify the name used when you reference the List class or interface.

import java.util.List;
...

...
java.awt.List myAwtList = new java.awt.List();
...

Multiple expressions in for loops 581


Real's HowTo PDF version

Use a generic toString()


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0432.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<String> list = new ArrayList<String>();
ClassUtils.toString( o, o.getClass(), list );
return o.getClass().getName().concat( list.toString() );
}

private static void toString( Object o, Class<?> clazz, List<String> 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()));
// output : ClassUtilsTest[hello=world, i=42]
}
}

Use a generic toString() 582


Real's HowTo PDF version

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()));
// output : 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 java.beans.Introspector.

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

Use a generic toString() 583


Real's HowTo PDF version

Use a Object.clone()
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0433.html

Consider the following example.

import java.util.Date;

class MyData {

private Date aDate;

MyData() {
aDate = new Date();
}

public Date getDate() {


return aDate;
}
public void setdate(Date d) {
aDate = d;
}
}

public class DemoClone {

public static void main(String args[]) {

MyData mydata = new MyData();


Date d = mydata.getDate();
System.out.println(d);
d.setTime(1000);
System.out.println(d);
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;

Use a Object.clone() 584


Real's HowTo PDF version

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

Static field, constructor and exception


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0444.html

Consider the following class

public class Foo {


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.

Static field, constructor and exception 585


Real's HowTo PDF version

public class Foo {


static Bar bar ;

static {
try {
bar = new Bar() ;
}
catch ( Exception e ) {
e.printStackTrace() ;
}
}
}

class Bar {
public Bar ( ) throws Exception {
}
}

Use a Label break


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0500.html

Labelled breaks allow breaking out of several levels of nested loops inside a pair of curly braces. This way,
you can almost simulate a GOTO!

class JavaGoto {
public static void main(String args[]) {
int max = 10;
int limit = 5;
int j = 0;
out: {
for (int row=0; row< max; row++ ) {
for (int col=0; col< max; col++ ) {
if( row == limit) break out;
}
j += 1;
}
}
System.out.println(j); // output 5
}
}

Put printStackTrace() into a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0537.html

Use a Label break 586


Real's HowTo PDF version

public class TestException {


public static void main(String args[]) {
try {
throw new Exception("for no reason!");
}
catch (Exception e) {
e.printStackTrace();
}
}
// output :
// java.lang.Exception: for no reason!
// at TestException.main(TestException.java:8)
}

You can 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.

Iterate enum values


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0655.html

public class EnumTest {

enum Simpsons {
HOMER ("Homer"),

Put printStackTrace() into a String 587


Real's HowTo PDF version

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

*/

Get fields and values from an Object


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-get-fields-and-values-from-an-object.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";
}

We want to list the fields and the values of an instance.

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

public class ObjectUtils {

Iterate enum values 588


Real's HowTo PDF version

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

Use a Hashtable
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0027.html

Hashtables are very useful for maintaining a 1-to-1 relationship between Objects. With an arbitary key, you
can retrieve easily an Object. In the following example, we retrieve a String array with a String.

String[] array1 = {"A","B","C"};

Get fields and values from an Object 589


Real's HowTo PDF version

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

Scan the content of a hashtable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0032.html

Enumeration keys = hash.keys();


while( keys.hasMoreElements() ) {
Object key = keys.nextElement();
Object value = hash.get(key);
}

Sort an array
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0008.html

JDK1.4+

case-sensitive

String[] myArray = new String[] {"foo","bar","baz"};


java.util.Arrays.sort(myArray);

case-insensitive

String[] myArray = new String[] {"foo","Bar","baz"};


java.util.Arrays.sort(myArray, java.text.Collator.getInstance());

less than JDK1.4

[ArraySorter.java]

Use a Hashtable 590


Real's HowTo PDF version

public class ArraySorter {


/*
** Sort in the same array
*/
public static void sort(Object[] a, Comparer comparer) {
sort(a, null, 0, a.length - 1, true, comparer);
}

/*
** Sort a and b, using a as the reference
*/
public static void sort(Object[] a, Object[] b,
int from, int to, boolean ascending, Comparer comparer) {
// No sort
if (a == null || a.length < 2) return;

// sort using Quicksort


int i = from, j = to;
Object center = a[ (from + to) / 2 ];
do {
if (ascending) {
while( (i < to) && (comparer.compare( center, a[i]) > 0) )
i++;
while( (j > from) && (comparer.compare(center, a[j]) < 0) )
j--;
}
else {
// Decending sort
while( (i < to) && (comparer.compare( center, a[i]) < 0) )
i++;
while( (j > from) && (comparer.compare(center, a[j]) > 0) )
j--;
}
if (i < j) {
// Swap elements
Object temp = a[i]; a[i] = a[j]; a[j] = temp;
// Swap in b array if needed
if (b != null) {
temp = b[i]; b[i] = b[j]; b[j] = temp;
}
}
if (i <= j) { i++; j--; }
} while(i <= j);
// Sort the rest
if (from < j) sort(a, b, from, j, ascending, comparer);
if (i < to) sort(a, b, i, to, ascending, comparer);
}

public static interface Comparer {


/**
* The interface implementation should compare the two
* objects and return an int using these rules:
* if (a > b) return > 0;
* if (a == b) return 0;

Sort an array 591


Real's HowTo PDF version

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

Initialize multidimensional array


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0036.html

Simply use braces...

static double[][] Rates = {


{0.50, 0.70, 0.40, 0.60},
{0.50, 1.10, 0.50, 0.80},
{0.80, 1.60, 0.70, 1.20},
{1.50, 2.90, 1.20, 2.10},
{2.50, 4.90, 2.00, 3.30},
{4.60, 8.50, 3.20, 5.00},
{6.40,11.00, 4.10, 6.00}
};

Initialize multidimensional array 592


Real's HowTo PDF version

Get array upperbound


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0280.html

class ArrayLength {
public static void main(String args[]) {
String[][] data = new String[3][4];
System.out.println("Dimension 1: " + data.length);
System.out.println("Dimension 2: " + data[0].length);
}
}

To get the number of dimensions :

public class ArrayDim {


public static void main(String args[]) {
String[][] data = new String[3][4];
System.out.println("This array has " + ArrayDim.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 );
}
}

Convert a String to an array or an array to a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0368.html

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

Get array upperbound 593


Real's HowTo PDF version

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

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

Convert a String to an array or an array to a String 594


Real's HowTo PDF version

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

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.

Sort Collection in reverse order


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0428.html

Sort Collection in reverse order 595


Real's HowTo PDF version

Arrays.sort (myArray, Collections.reverseOrder());

Resize an array
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0431.html

Arrays cannot be resized dynamically. If you want a dynamic data structure with random access, you use a
Collection (Map, ArrayList,...).

If you need to expand, you can use System.arraycopy() method to copy the content of an array to another
one.

import java.lang.reflect.Array;

public class ArrayUtils {

private ArrayUtils() {}

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

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
}

But a better way is to use a Vector or an ArrayList. ArrayList is roughly equivalent to Vector, except that it
is unsynchronized.

Resize an array 596


Real's HowTo PDF version

import java.util.ArrayList;

public class ArrayListDemo {


public static void main (String arg[]) {
ArrayListDemo x = new ArrayListDemo();
x.doit1();
x.doit2();
}

public void doit1() {


// single dimension
ArrayList list = new ArrayList();
list.add("a");
list.add("b");
int size = list.size(); // 2
System.out.println("Array 1 " +list.get(0); // a
}

public void doit2() {


// multi dimensions
ArrayList list = new ArrayList();
ArrayList l1 = new ArrayList();
l1.add("a");
ArrayList l2 = new ArrayList();
l2.add("b");
ArrayList l3 = new ArrayList();
l3.add("c");

list.add(l1);
list.add(l2);
list.add(l3);

int size1 = list.size(); // 3


int size2 = ((ArrayList)list.get(0)).size(); // 1
System.out.println("Array 2 "
+ ((ArrayList)list.get(1)).get(0)); // b
}
}

Dump array content (JDK1.5)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0465.html

JDK1.5+

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.

Dump array content (JDK1.5) 597


Real's HowTo PDF version

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

java.util.Arrays provides new ways to dump the content of an array. It's even possible to dump
muti-dimensional arrays.

public class Test {

public static void main(String args[]) {


String s[] = {"a", "b", "c", "d"};
double d [][]= {
{0.50, 0.70, 0.40, 0.60},
{0.50, 1.10, 0.50, 0.80}
};
System.out.println(java.util.Arrays.toString(s));
System.out.println(java.util.Arrays.deepToString(d));
// output
// [a, b, c, d]
// [[0.5, 0.7, 0.4, 0.6], [0.5, 1.1, 0.5, 0.8]]
}
}

You can also use the new shorthand notation to iterate through an array :

public class Test {


public static void main(String args[]) {
String s[] = {"a", "b", "c", "d"};
for (String element : s) {
System.out.println(element);
}
}
}

Initialize a static array


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0475.html

public class InitStaticArray {

static Integer[] integerArray;


static {

Initialize a static array 598


Real's HowTo PDF version

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

Sort an Hashtable
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0478.html

Data in hashtable are not sorted. We extract the keys and sort them.

import java.util.*;

public class HashtableTest {

static String[] array1 = {"C","B","A"};


static String[] array2 = {"1","2","3"};

public static void main(String args[]) {

Hashtable h = new Hashtable();


h.put(array1[0], array2[0]);
h.put(array1[1], array2[1]);
h.put(array1[2], array2[2]);

// unsorted keys output


Iterator it = h.keySet().iterator();
while (it.hasNext()) {
String element = (String)it.next();
System.out.println(element + " " + (String)h.get(element));
}

System.out.println("============");

// sorted keys output thanks to T. GUIRADO for the tip!


Vector v = new Vector(h.keySet());
Collections.sort(v);
it = v.iterator();
while (it.hasNext()) {
String element = (String)it.next();

Sort an Hashtable 599


Real's HowTo PDF version

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.

Eliminate "[unchecked] unchecked call ..." compiler warning


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0521.html

import java.util.*;

public class ArrayListGeneric {


public static void main(String[] args) {
ArrayList data = new ArrayList();
data.add("hello");
data.add("world");

Iterator<String> it = data.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
}
}

When compiling the above class, the compiler (jdk1.5) emits the following warnings :

C:\ArrayListGeneric.java:21:
warning: [unchecked] unchecked call to add(E) as a member of the raw type

Eliminate "[unchecked] unchecked call ..." compiler warning 600


Real's HowTo PDF version

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

Eliminate "[unchecked] unchecked call ..." compiler warning 601


Real's HowTo PDF version

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.

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>

Sort on many fields


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0520.html

We want to sort a Collection of Person objects based on their LastName and Firstname.

First the Person class

class Person implements Comparable {


String firstName, lastName;

public Person(String f, String l) {


this.firstName = f;
this.lastName = l;

Eliminate "[unchecked] unchecked call ..." compiler warning 602


Real's HowTo PDF version

public String getFirstName() {


return firstName;
}

public String getLastName() {


return lastName;
}

public String toString() {


return "[ firstname=" + firstName + ",lastname=" + lastName + "]";
}

public int compareTo(Object obj) {


Person emp = (Person) obj;
int deptComp = firstName.compareTo(emp.getFirstName());

return ((deptComp == 0) ? lastName.compareTo(emp.getLastName())


: deptComp);
}

public boolean equals(Object obj) {


if (!(obj instanceof Person)) {
return false;
}
Person emp = (Person) obj;
return firstName.equals(emp.getFirstName())
&& lastName.equals(emp.getLastName());
}
}

then we need a class to implement the Comparable interface. It's in there where we put the logic behind the
sorting.

import java.util.Comparator;

class PersonComparator implements Comparator{


public int compare(Object obj1, Object obj2) {
Person emp1 = (Person) obj1;
Person emp2 = (Person) obj2;

int nameComp = emp1.getLastName().compareTo(emp2.getLastName());

return ((nameComp == 0) ?
emp1.getFirstName().compareTo(emp2.getFirstName()) :
nameComp);
}
}

To test it :

import java.util.ArrayList;

Sort on many fields 603


Real's HowTo PDF version

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Iterator;

public class TestSort {


public static void main(String args[]) {
String Smith[] = { "Real", "Vincent", "Nathalie", "Christine" };
String Simpsons[] = { "Bart", "Lisa", "Marge", "Homer", "Maggie" };

ArrayList names = new ArrayList();

// do the smith
for(int i = 0 ; i < Smith.length ; i ++) {
Person one = new Person(Smith[i],"Smith");
names.add(one);
}

// do the simpsons
for(int i = 0 ; i < Simpsons.length ; i ++) {
Person one = new Person(Simpsons[i],"Simpsons");
names.add(one);
}

System.out.println("BEFORE:");
Iterator iter1 = names.iterator();
while (iter1.hasNext()) {
System.out.println(iter1.next());
}

// now sort everything


Collections.sort(names, new PersonComparator());

System.out.println("AFTER:");
Iterator iter2 = names.iterator();
while (iter2.hasNext()) {
System.out.println(iter2.next());
}

/*
output :
BEFORE:
[ firstname=Real,lastname=Smith]
[ firstname=Vincent,lastname=Smith]
[ firstname=Nathalie,lastname=Smith]
[ firstname=Christine,lastname=Smith]
[ firstname=Bart,lastname=Simpsons]
[ firstname=Lisa,lastname=Simpsons]
[ firstname=Marge,lastname=Simpsons]
[ firstname=Homer,lastname=Simpsons]
[ firstname=Maggie,lastname=Simpsons]
AFTER:
[ firstname=Bart,lastname=Simpsons]
[ firstname=Homer,lastname=Simpsons]

Sort on many fields 604


Real's HowTo PDF version

[ 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]
*/
}
}

Optimize Collection usage


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0553.html

From Usenet, a post (by "Ed") to demonstrate that depending on your need, choosing the right Collection
implementation can be really important.

In the demonstration, we read a huge text file war-and-peace.txt and then count the duplicated words. as
you can see depending on the Collection used, the execution time is very different!

import java.util.*;
import java.io.*;

class TestCollectionPerformance {
private static String TEXT_BOOK_NAME = "war-and-peace.txt";

public static void main(String[] args) {


try {
String text = readText(); // Read text into RAM
countDuplicateWords(text, new HashSet<String>());
countDuplicateWords(text, new TreeSet<String>());
countDuplicateWords(text, new ArrayList<String>());
countDuplicateWords(text, new LinkedList<String>());
}
catch (Throwable t) {
System.out.println(t.toString());
}
}

private static String readText() throws Throwable {


BufferedReader reader =
new BufferedReader(new FileReader(TEXT_BOOK_NAME));
String line = null;
StringBuffer text = new StringBuffer();
while ((line = reader.readLine()) != null) {
text.append(line + " ");
}
return text.toString();

Optimize Collection usage 605


Real's HowTo PDF version

private static void countDuplicateWords(String text,


Collection<String> listOfWords) {
int numDuplicatedWords = 0;
long startTime = System.currentTimeMillis();
for (StringTokenizer i = new StringTokenizer(text);
i.hasMoreElements();) {
String word = i.nextToken();
if (listOfWords.contains(word)) {
numDuplicatedWords++;
}
else {
listOfWords.add(word);
}
}
long endTime = System.currentTimeMillis();
System.out.println(numDuplicatedWords + " duplicated words. " +
"Using " + listOfWords.getClass().getName() +
", time = " + (endTime - startTime) + "ms.");
}
}

Result :

522396 duplicated words. Using java.util.HashSet, time = 453ms.


522396 duplicated words. Using java.util.TreeSet, time = 1031ms.
522396 duplicated words. Using java.util.ArrayList, time = 100937ms.
522396 duplicated words. Using java.util.LinkedList, time = 129375ms.
• A Set offers a collection of unique elements.
• An HashSet maintains its collection in an unordered manner.
• A TreeSet keeps the elements in the collection in sorted order.
• A List provides ordered access (by index), but it doesn't guarantee uniqueness.
• The ArrayList provides a collection backed by an array. It provides quick indexed access to its elements,
and works best when elements are only added and removed at the end. To make this happen, ArrayList
performs an internal move operation when an element is added or removed.
• The LinkedList is best when add and remove operations happen anywhere, not only at the end. LinkList
doesn't do an internal move operation for an element insert or remove, it just manipulates reference
pointers. But LinkedList's added flexibility comes at an added cost -- it results in much slower indexed
operations.

Sort an HashMap
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0561.html

Sort based on the keys

Sort an HashMap 606


Real's HowTo PDF version

Map yourMap= new HashMap();


// put some tuples in yourMap ...
Map sortedMap = new TreeMap(yourMap);

To sort only the keys :

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedSet;
import 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();
// 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

Sort an HashMap 607


Real's HowTo PDF version

Set ref = map.keySet();


Iterator it = ref.iterator();

while (it.hasNext()) {
String file = (String)it.next();
}

Get keys corresponding to a value from a Map


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0564.html

This method returns a List of the keys corresponding to a given value.

[Java 5]

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import 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);
}
}
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]

Get keys corresponding to a value from a Map 608


Real's HowTo PDF version

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import 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"));
}
}

Iterate a Collection and remove an item


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

Iterate a Collection and remove an item 609


Real's HowTo PDF version

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")) {
iter.remove();
}
else {
System.out.println(s);
}
}

Iterate a Collection and remove an item 610


Real's HowTo PDF version

for(String s: list)
{
System.out.println(s);
}
}

/*
output :
Bart
Lisa
Marge
Homer
Maggie
Bart
Lisa
Marge
Homer
Maggie
*/
}

Count distinct elements in a Vector


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0377.html

Submitted by T GUIRADO

/**
** This method counts distinct elements from a given position in vector
** containing series of element.
** Arguments : source = vector containing the vectors of elements
** position = which element to search, first position = 0
** count = serie length
**
** ex :
** source = A,B,C D,E,F D,F,G
** length is 3
** from position 0 in each series we have A,D,D
** this method returns 2 because there are 2 distinct elements (A and D)
** from position 2 in each series we have C,F,G
** this method returns 2 because there are 3 distinct elements (C,FandG)
**/
protected synchronized int countDistinctElements
(Vector source,int position,int count){
Vector v = null;
for (int i = 0 ; i < source.size() ; i++) {
boolean isFound = false;
if ( i % count == position ) {
if ( null != v ) {
for (int j = 0 ; j < v.size() ; j++) {

Count distinct elements in a Vector 611


Real's HowTo PDF version

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

Dump the content of a Collection (JDK 1.5)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0628.html

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

Dump the content of a Collection (JDK 1.5) 612


Real's HowTo PDF version

for (String character: theSimpsons) {


System.out.println(character);
}
}
}

Or convert the list as an Array :

System.out.println(java.util.Arrays.toString(theSimpsons.toArray()));

/*
output : [Bart, Lisa, Marge, Barney, Homer, Maggie]
*/

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

Dump the content of a Collection (JDK 1.5) 613


Real's HowTo PDF version

Initialize a Collection
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0633.html

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

Initialize a Collection 614


Real's HowTo PDF version

}
}

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

Initialize a Collection 615


Real's HowTo PDF version

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

public static void dump(List<String> list) {


for (String s:list) {
System.out.println(s);
}
}
}

Merge (or add) two arrays into one


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

Merge (or add) two arrays into one 616


Real's HowTo PDF version

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


private 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) {
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]
*/
}
}

Define an array (or Map, or ENUM) of functions


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0005.html

Define an array (or Map, or ENUM) of functions 617


Real's HowTo PDF version

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

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.

Define an array (or Map, or ENUM) of functions 618


Real's HowTo PDF version

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

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

Define an array (or Map, or ENUM) of functions 619


Real's HowTo PDF version

}
}

NOTE : Using this technique, it's possible to simulate "switch ... case" based on a string value.

Join a List as a String


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

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

Join a List as a String 620


Real's HowTo PDF version

Remove duplicates from a List


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-remove-duplicates-in-a-list.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]
}
}

Order is preserved

import java.util.HashSet;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class ListUtils {

private ListUtils() {}

@SuppressWarnings("unchecked")

Remove duplicates from a List 621


Real's HowTo PDF version

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

Convert a Map to a Properties (or vice versa)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-convert-map-to-properties.html

Map to Properties

public static Properties mapToProperties(Map<String, String> map) {


Properties p = new Properties();
Set<Map.Entry<String,String>> set = map.entrySet();
for (Map.Entry<String,String> entry : set) {
p.put(entry.getKey(), entry.getValue());
}
return p;
}

or simply

Map<string,string> map = ...


Properties props = new Properties();
props.putAll(map);

Convert a Map to a Properties (or vice versa) 622


Real's HowTo PDF version

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

Use an INI file (properties)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0024.html

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/

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=&8djsx
DBlocation=bigone

[JAVA code]

import java.util.*;
import java.io.*;

Use an INI file (properties) 623


Real's HowTo PDF version

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

Use an INI file (properties) 624


Real's HowTo PDF version

This ok with an application but you can't do it from an Applet since you can't write directly on the server
without some kind of a server-side process.

To read a Properties file via an Applet, load the Properties files this way :

p.load((new URL(getCodeBase(), "user.props")).openStream());

A Properties file stored in a JAR can be loaded this way :

URL url =
ClassLoader.getSystemResource("/com/rgagnon/config/system.props");
if (url != null) props.load(url.openStream());

See also this HowTo (Load a properties file), this one (Accentuated characters in
Properties/ResourceBundle file) and finally this one too (Have a multi-line value in a properties file)!

Load a properties file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0434.html

import java.util.Properties;
import java.io.File;
import java.io.IOException;
import java.io.FileInputStream;
import 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
*/

Load a properties file 625


Real's HowTo PDF version

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)

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

Accentuated characters in Properties/ResourceBundle file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0492.html

The rules are

• Only use ISO Latin 1 characters in the Properties/ResourceBundle files


• For other characters use the \u.... notation
• To avoid having to type all the \u... notation manually, use the native2ascii tool (included with the
SDK).

Have a multi-line value in a properties file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0503.html

You add a slash ("\") to continue the value on the next line.

Take the following properties file :


[props.properties]

prop1=first line of prop1 \


second line of prop1\
third line of prop1
prop2=first line of prop2 \n \

Accentuated characters in Properties/ResourceBundle file 626


Real's HowTo PDF version

second line of prop2 \n \


third line of prop2

A program to read the properties file :


[Hello.java]

public class Hello {


public static void main(String args[]) throws Exception{
Hello h = new Hello();
h.doit();
}
public void doit() throws Exception{
// properties in the classpath
java.util.Properties props = new java.util.Properties();
java.net.URL url = ClassLoader.getSystemResource("props.properties");
props.load(url.openStream());
System.out.println("prop1 :\n " + props.get("prop1"));
System.out.println("prop2 :\n " + props.get("prop2"));
}
}

The output

>java Hello
prop1 :
first line of prop1 second line of prop1third line of prop1
prop2 :
first line of prop2
second line of prop2
third line of prop2

Use XML with Properties


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0578.html

import java.util.*;
import java.io.*;

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

public void doit() {


try{
Properties p = new Properties();

p.put("today", new Date().toString());

Have a multi-line value in a properties file 627


Real's HowTo PDF version

p.put("user", "Bob");

FileOutputStream out = new FileOutputStream("user.props");


p.storeToXML(out,"props updated");

FileInputStream in = new FileInputStream("user.props");

p.loadFromXML(in);
p.list(System.out);
/*
output :
-- listing properties --
today=Thu Aug 09 22:45:11 EDT 2007
user=Bob
*/
}
catch (Exception e) {
e.printStackTrace();
}
}
}

The XML looks like

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>props updated</comment>
<entry key="user">Bob</entry>
<entry key="today">Thu Aug 09 22:45:11 EDT 2007</entry>
</properties>

Use the Registry to store informations


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0421.html

With JDK1.4, the Preferences class can use the Windows registry (on Unix, a file is used) :

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

Use XML with Properties 628


Real's HowTo PDF version

Preferences p = Preferences.userRoot();
p.put(REALKEY, "bar");

// read back from HKEY_CURRENT_USER


System.out.println(p);
System.out.println(p.get(REALKEY, "HKCU houston we have a problem"));

// write into HKLM\Software\Javasoft\Prefs\com.rgagnon.foo


p = Preferences.systemRoot();
p.put(REALKEY, "barbar");

// read back from HKEY_LOCAL_MACHINE


System.out.println(p);
System.out.println(p.get(REALKEY, "HKLM houston we have a problem"));
}
}

See also this How-to (Query Windows registry) 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

Sort Properties when saving


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0614.html

Create a SortedProperties class which extend the regular Properties. Then override the keys() method to
return the sorted keys instead.

import java.util.Collections;
import java.util.Enumeration;
import java.util.Properties;
import 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();
}

Use the Registry to store informations 629


Real's HowTo PDF version

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

Resolve environment variable in a property value


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-resolve-environment-variable-in-property-value.html

A common way to use environment variables in a Properties file is to refer to them with the following
syntax :

value=The value is ${variableName}

Sort Properties when saving 630


Real's HowTo PDF version

The regular Properties class can't resolve the real value form the environment variable named
variableName.

One way is to use this small utility

import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PropertiesUtils {

private PropertiesUtils() {}

private static String resolveValueWithEnvVars(String value) {


if (null == value) {
return null;
}

Pattern p = Pattern.compile("\\$\\{(\\w+)\\}|\\$(\\w+)");
Matcher m = p.matcher(value);
StringBuffer sb = new StringBuffer();
while (m.find()) {
String envVarName = null == m.group(1) ? m.group(2) : m.group(1);
String envVarValue = System.getenv(envVarName);
m.appendReplacement(sb,
null == envVarValue ? "" : Matcher.quoteReplacement(envVarValue));
}
m.appendTail(sb);
return sb.toString();
}
}

to use it :

public static void main(String[] args) {


// For the demo, create a Properties, normally you will read Properties from file
Properties p = new Properties();
p.put("path", "${TEMP}\\${USERDOMAIN}");

System.out.println("path value : "


+ PropertiesUtils.resolveValueWithEnvVars(p.getProperty("path")));
/*
* output on my machine :
* path value :C:\Users\REAL_U~1\AppData\Local\Temp\RealNet001
* ------------------------------------ ----------
* TEMP USERDOMAIN
*/
}

NOTE: Apache Commons Lang StrSubstitutor class can be used to do something similar but with Java
System Properties (not OS environment variable) or user-supplied map of values.

Resolve environment variable in a property value 631


Real's HowTo PDF version

Written and compiled Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Resolve environment variable in a property value 632


Networking
java-net

Extract network card address


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0369.html

JDK1.6
java.net.NetworkInterface

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

public class ListNetsEx


{
public static void main(String args[])
throws SocketException
{
Enumeration nets =
NetworkInterface.getNetworkInterfaces();
for (NetworkInterface netint : Collections.list(nets))
displayInterfaceInformation(netint);
}

static void displayInterfaceInformation(NetworkInterface netint)


throws SocketException
{
System.out.println("Display name: "
+ netint.getDisplayName());
System.out.println("Hardware address: "
+ Arrays.toString(netint.getHardwareAddress()));
}
}

JDK1.5 or less
One way, without using JNI, is to launch an external utility and interpret the output.

In Windows, "arp -a" will return the MAC addresses of all adapters that have TCP/IP bound to them and have
recently (default < 5 mins) resolved an IP address. Otherwise, in NT/2K/XP, "ipconfig /all" will return all
relevant network info for IP-bound adapters, including the MAC address (displayed as "physical address").

In Linux, "ifconfig" does something similar.

Networking 633
Real's HowTo PDF version

Example for Windows

import java.net.InetAddress;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.text.ParseException;
import java.util.StringTokenizer;

//
// inspired by
// http://forum.java.sun.com/thread.jspa?messageID=902023
//

public final class NetworkUtils {

private final static int MACADDR_LENGTH = 17;


private final static String WIN_OSNAME = "Windows";
private final static String WIN_MACADDR_REG_EXP =
"^[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}$";
private final static String WIN_MACADDR_EXEC = "ipconfig /all";

public final static String getMacAddress() throws IOException {


String os = System.getProperty("os.name");
try {
if (os.startsWith(WIN_OSNAME)) {
return winMacAddress(winIpConfigCommand());
}
// other OS left as an exercise !
// LINUX --> else if (os.startsWith("Linux")) { ...
// ...
// Process p = Runtime.getRuntime().exec("ifconfig");
// MAC OSX --> else if(os.startsWith("Mac OS X")) { ...
// ...
// Process p = Runtime.getRuntime().exec("ifconfig");
else {
throw new IOException("OS not supported : " + os);
}
}
catch(ParseException e) {
e.printStackTrace();
throw new IOException(e.getMessage());
}
}

private final static String winMacAddress(String ipConfigOutput)


throws ParseException {
String localHost = null;
try {
localHost = InetAddress.getLocalHost().getHostAddress();
}
catch(java.net.UnknownHostException ex) {
ex.printStackTrace();

Extract network card address 634


Real's HowTo PDF version

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

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

Extract network card address 635


Real's HowTo PDF version

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

Get the workstation name/ip


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0390.html

public class NetInfo {


public static void main(String[] args) {
new NetInfo().say();
}

public void say() {


try {
java.net.InetAddress i = java.net.InetAddress.getLocalHost();
System.out.println(i); // name and IP address
System.out.println(i.getHostName()); // name
System.out.println(i.getHostAddress()); // IP address only
}
catch(Exception e){e.printStackTrace();}
}
}

The output

> java NetInfo


realone/209.142.72.112
realone
209.142.72.112

To list all the interfaces available on a workstation :


[JDK1.4]

Get the workstation name/ip 636


Real's HowTo PDF version

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

public class IPAdress {


public void getInterfaces (){
try {
Enumeration e = NetworkInterface.getNetworkInterfaces();

while(e.hasMoreElements()) {
NetworkInterface 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();
ip.getInterfaces();
}
}

The output

> java IPAdress


Net interface: lo
IP address: /127.0.0.1
Net interface: eth0
IP address: /194.168.0.1
Net interface: eth1
IP address: /164.254.147.20
Net interface: ppp0
IP address: /64.68.115.69

Windows

A "low-tech" way to get the computer name (can be useful if there is no network card) is to use the
environment variable COMPUTERNAME (at least on modern Windows installation).

[JDK1.4 or less] Pass it to your JVM as java -Dcomputername="%COMPUTERNAME%" ... and then get the
value with System.getProperty("computername")

Get the workstation name/ip 637


Real's HowTo PDF version

[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.

Find a port number not in use


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0412.html

On Windows, "netstat -an" list the ports currently in use.

Take a look at http://www.iana.org/assignments/port-numbers for a list of assigned numbers.

Disable DNS caching


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0445.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 un-successful
name lookups from the name service. The value is specified as as integer to
indicate the number of seconds to cache the failure for un-successful lookups.

A value of 0 indicates "never cache". A value of -1 indicates "cache forever".

sun.net.inetaddr.ttl
This is a sun private system property which corresponds to networkaddress.cache.ttl.
It takes the same value and has the same meaning, but can be set as a command-line
option. However, the preferred way is to use the security property mentioned above.

Find a port number not in use 638


Real's HowTo PDF version

sun.net.inetaddr.negative.ttl
This is a sun private system property which corresponds to networkaddress.cache.negative.tt
It takes the same value and has the same meaning, but can be set as a command-line option.
However, the preferred way is to use the security property mentioned above.

So you can disable caching by adding -Dsun.net.inetaddr.ttl=0 on the command line starting the JVM. But
you can't set the value of networkaddress.cache.ttl on the command line. You can set the required value in the
java.security file located in %JRE%\lib\security

networkaddress.cache.ttl=60
networkaddress.cache.negative.ttl=10

or set the value in your code with

java.security.Security.setProperty("networkaddress.cache.ttl" , "0");

ref : J2SE 1.4 Net properties

JDK1.6 or more

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

See also Examine the internal DNS cache

Examine the internal DNS cache


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-examine-internal-dns-cache.html

Once an application has performed network access (i.e. urlconnection, parsing of xml document with external
references, etc), the DNS settings get cached internally so any subsequent operation will use the previously
read settings to achieve a better performance. There is one cache for successful lookups and one for
unsuccessful lookups. To get the contents of 2 caches, we are using introspection because these are private
elements of the InetAdress object.

import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class DNSCache {

Disable DNS caching 639


Real's HowTo PDF version

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

// put some values in the internal DNS cache

// good DNS name


InetAddress.getByName("stackoverflow.com");
InetAddress.getByName("www.google.com");
InetAddress.getByName("www.rgagnon.com");
try {
// bad DNS name
InetAddress.getByName("bad.rgagnon.com");
}
catch (UnknownHostException e) {
// do nothing
}

// dump the good DNS entries


String addressCache = "addressCache";
System.out.println("---------" + addressCache + "---------");
printDNSCache(addressCache);

// dump the bad DNS entries


String negativeCache = "negativeCache";
System.out.println("---------" + negativeCache + "---------");
printDNSCache(negativeCache);
}

/**
* By introspection, dump the InetAddress internal DNS cache
*
* @param cacheName can be addressCache or negativeCache
* @throws Exception
*/

@SuppressWarnings({ "rawtypes", "unchecked" })


private static void printDNSCache(String cacheName) throws Exception {
Class<InetAddress> iaclass = InetAddress.class;
Field acf = iaclass.getDeclaredField(cacheName);
acf.setAccessible(true);
Object addressCache = acf.get(null);
Class cacheClass = addressCache.getClass();
Field cf = cacheClass.getDeclaredField("cache");
cf.setAccessible(true);
Map<String, Object> cache = (Map<String, Object>) cf.get(addressCache);
for (Map.Entry<String, Object> hi : cache.entrySet()) {
Object cacheEntry = hi.getValue();
Class cacheEntryClass = cacheEntry.getClass();
Field expf = cacheEntryClass.getDeclaredField("expiration");
expf.setAccessible(true);
long expires = (Long) expf.get(cacheEntry);

Field af = cacheEntryClass.getDeclaredField("addresses"); // JDK 1.7, older version ma


af.setAccessible(true);
InetAddress[] addresses = (InetAddress[]) af.get(cacheEntry);

Examine the internal DNS cache 640


Real's HowTo PDF version

List<String> ads = new ArrayList<String>(addresses.length);

for (InetAddress address : addresses) {


ads.add(address.getHostAddress());
}

System.out.println(hi.getKey() + " "+new Date(expires) +" " +ads);


}
}
}

Output

---------addressCache---------
0.0.0.0 Wed Jul 22 15:41:35 EDT 2015 [0.0.0.0]
stackoverflow.com Wed Jul 22 15:41:35 EDT 2015 [198.252.206.16]
www.google.com Wed Jul 22 15:41:35 EDT 2015 [173.194.123.49, 173.194.123.50, 173.194.123.48, 17
www.rgagnon.com Wed Jul 22 15:41:35 EDT 2015 [72.55.186.40]
---------negativeCache---------
bad.rgagnon.com Wed Jul 22 15:41:15 EDT 2015 [0.0.0.0]

In this HowTo, we saw that is possible to change the default behaviour of DNS caching.

To disable the caching

public class DNSCache {


public static void main(String[] args) throws Exception {
java.security.Security.setProperty("networkaddress.cache.ttl" , "0"); // no cache
java.security.Security.setProperty("networkaddress.cache.negative.ttl" , "0"); // no cache
...

and the caches are empty

---------addressCache---------
---------negativeCache---------

To cache forever

public class DNSCache {


public static void main(String[] args) throws Exception {
java.security.Security.setProperty("networkaddress.cache.ttl" , "-1"); // cache forever
java.security.Security.setProperty("networkaddress.cache.negative.ttl" , "-1"); // cache f
...

and the result is

---------addressCache---------
0.0.0.0 Wed Dec 31 18:59:59 EST 1969 [0.0.0.0]
stackoverflow.com Wed Dec 31 18:59:59 EST 1969 [198.252.206.16]
www.google.com Wed Dec 31 18:59:59 EST 1969 [173.194.123.116, 173.194.123.114, 173.194.123.113,
www.rgagnon.com Wed Dec 31 18:59:59 EST 1969 [72.55.186.40]

Examine the internal DNS cache 641


Real's HowTo PDF version

---------negativeCache---------
bad.rgagnon.com Wed Dec 31 18:59:59 EST 1969 [0.0.0.0]

Allow user:password in URL


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../pbdetails/pb-0249.html

The following URL syntax is no longer supported in Internet Explorer or in Windows Explorer after you
install the MS04-004 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

Encode/Decode to/from Base64


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0598.html

Allow user:password in URL 642


Real's HowTo PDF version

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.

Using javax.mail.internet.MimeUtility

import javax.mail.internet.MimeUtility;
import java.io.*;

public class Base64Utils {

private 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
*/
}

Encode/Decode to/from Base64 643


Real's HowTo PDF version

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

MiGBase64

MiGBase64 is a very fast Base64 Codec written in Java. http://migbase64.sourceforge.net/.

Lookup using MX record to validate mail server


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0452.html

The best you can do to verify if an email address is real is to verify if there is a mail server registered to the
domain name.

import java.util.Hashtable;
import javax.naming.*;
import javax.naming.directory.*;

public class MXLookup {

Encode/Decode to/from Base64 644


Real's HowTo PDF version

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

Lookup using MX record to validate mail server 645


Real's HowTo PDF version

Two (better method):


Connect to the servers determined by your code snippet. BUT (and the code below doesn't do this) they
must be tried from lowest preference to highest to be absolutely correct.

Once you have connected, you create the SMTP envelope, but you don't put anything in it. This is the point
at which most servers will give up the dirt on whether or not an address is valid. If an envelope cannot be
built, we know that the address is invalid.

The reason for connecting in order of preference:

Imagine ABC company has an Internet conneciton and runs their own mail server for abc.com. To prevent
bounces and other mail errors if their connection or server should be down, their provider isp.com agrees to
set up a 'store and forward' scheme for their mail. If abc.com is not available, then isp.com gets the message
and when abc.com is again available, the message gets forwarded. The MX records would look something
like:

MX 1 abc.com
MX 5 isp.com

Now, imagine that you connect to isp.com and try to send a message. The mail server at isp.com doesn't
have the actual user list to know which addresses are valid, it just accepts everything and relies on abc.com
to sort out the bounces.

If these are not checked in the proper order, there will be no errors for invalid addresses.

Yahoo appears to use a store and forward mechanism to its own internal servers, thus conclusively
verifying a yahoo address is not possible. I suspect that hotmail is the same.

It is not possible to verify an address on a domain that uses a catch-all account as the catch account will
receive the mail (it does, however, mean that someone will at least SEE the message).

import java.io.*;
import java.net.*;
import java.util.*;
import javax.naming.*;
import javax.naming.directory.*;

public class SMTP {


private static int hear( BufferedReader in ) throws IOException {
String line = null;
int res = 0;

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


String pfx = line.substring( 0, 3 );
try {
res = Integer.parseInt( pfx );
}
catch (Exception ex) {
res = -1;

Lookup using MX record to validate mail server 646


Real's HowTo PDF version

}
if ( line.charAt( 3 ) != '-' ) break;
}

return res;
}

private static void say( BufferedWriter wr, String text )


throws IOException {
wr.write( text + "\r\n" );
wr.flush();

return;
}

private static ArrayList getMX( String hostName )


throws NamingException {
// Perform a DNS lookup for MX records in the domain
Hashtable env = new Hashtable();
env.put("java.naming.factory.initial",
"com.sun.jndi.dns.DnsContextFactory");
DirContext ictx = new InitialDirContext( env );
Attributes attrs = ictx.getAttributes
( hostName, new String[] { "MX" });
Attribute attr = attrs.get( "MX" );

// if we don't have an MX record, try the machine itself


if (( attr == null ) || ( attr.size() == 0 )) {
attrs = ictx.getAttributes( hostName, new String[] { "A" });
attr = attrs.get( "A" );
if( attr == null )
throw new NamingException
( "No match for name '" + hostName + "'" );
}

// Huzzah! we have machines to try. Return them as an array list


// NOTE: We SHOULD take the preference into account to be absolutely
// correct. This is left as an exercise for anyone who cares.
ArrayList res = new ArrayList();
NamingEnumeration en = attr.getAll();

while ( en.hasMore() ) {
String x = (String) en.next();
String f[] = x.split( " " );
if ( f[1].endsWith( "." ) )
f[1] = f[1].substring( 0, (f[1].length() - 1));
res.add( f[1] );
}
return res;
}

public static boolean isAddressValid( String address ) {


// Find the separator for the domain name
int pos = address.indexOf( '@' );

Lookup using MX record to validate mail server 647


Real's HowTo PDF version

// If the address does not contain an '@', it's not valid


if ( pos == -1 ) return false;

// Isolate the domain/machine name and get a list of mail exchangers


String domain = address.substring( ++pos );
ArrayList mxList = null;
try {
mxList = getMX( domain );
}
catch (NamingException ex) {
return false;
}

// Just because we can send mail to the domain, doesn't mean that the
// address is valid, but if we can't, it's a sure sign that it isn't
if ( mxList.size() == 0 ) return false;

// Now, do the SMTP validation, try each mail exchanger until we get
// a positive acceptance. It *MAY* be possible for one MX to allow
// a message [store and forwarder for example] and another [like
// the actual mail server] to reject it. This is why we REALLY ought
// to take the preference into account.
for ( int mx = 0 ; mx < mxList.size() ; mx++ ) {
boolean valid = false;
try {
int res;
Socket skt = new Socket( (String) mxList.get( mx ), 25 );
BufferedReader rdr = new BufferedReader
( new InputStreamReader( skt.getInputStream() ) );
BufferedWriter wtr = new BufferedWriter
( new OutputStreamWriter( skt.getOutputStream() ) );

res = hear( rdr );


if ( res != 220 ) throw new Exception( "Invalid header" );
say( wtr, "EHLO orbaker.com" );

res = hear( rdr );


if ( res != 250 ) throw new Exception( "Not ESMTP" );

// validate the sender address


say( wtr, "MAIL FROM: <[email protected]>" );
res = hear( rdr );
if ( res != 250 ) throw new Exception( "Sender rejected" );

say( wtr, "RCPT TO: <" + address + ">" );


res = hear( rdr );

// be polite
say( wtr, "RSET" ); hear( rdr );
say( wtr, "QUIT" ); hear( rdr );
if ( res != 250 )
throw new Exception( "Address is not valid!" );

Lookup using MX record to validate mail server 648


Real's HowTo PDF version

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[] = {
"[email protected]", // Valid address
"[email protected]", // Invalid domain name
"[email protected]", // Invalid address
"[email protected]" // Failure of this method
};

for ( int ctr = 0 ; ctr < testData.length ; ctr++ ) {


System.out.println( testData[ ctr ] + " is valid? " +
isAddressValid( testData[ ctr ] ) );
}
return;
}
}

S.Boerner has this comments about this HowTo :

The method SMTP::getMX() in the second example throws an ArrayIndexOutOfBoundsException while


getting the mailhost via the "A" attribute at:

while ( en.hasMore() ) {
String x = (String) en.next();
String f[] = x.split( " " );
if ( f[1].endsWith( "." ) )

The "A" attribute returns only an address list, so f.length is always 1. I used something like:

boolean hasMX = "MX".equals(attr.getID());

and later

if (hasMX)
{
mailhost = f[1];
}
else

Lookup using MX record to validate mail server 649


Real's HowTo PDF version

{
mailhost = f[0];
}

Here my proposed fix :

import java.io.*;
import java.net.*;
import java.util.*;
import javax.naming.*;
import 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();
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 )

Lookup using MX record to validate mail server 650


Real's HowTo PDF version

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
// to take the preference into account.
for ( int mx = 0 ; mx &lt; mxList.size() ; mx++ ) {
boolean valid = false;

Lookup using MX record to validate mail server 651


Real's HowTo PDF version

try {
int res;
//
Socket skt = new Socket( (String) mxList.get( mx ), 25 );
BufferedReader rdr = new BufferedReader
( new InputStreamReader( skt.getInputStream() ) );
BufferedWriter wtr = new BufferedWriter
( new OutputStreamWriter( skt.getOutputStream() ) );

res = hear( rdr );


if ( res != 220 ) throw new Exception( "Invalid header" );
say( wtr, "EHLO rgagnon.com" );

res = hear( rdr );


if ( res != 250 ) throw new Exception( "Not ESMTP" );

// validate the sender address


say( wtr, "MAIL FROM: <[email protected]>" );
res = hear( rdr );
if ( res != 250 ) throw new Exception( "Sender rejected" );

say( wtr, "RCPT TO: <" + address + ">" );


res = hear( rdr );

// be polite
say( wtr, "RSET" ); hear( rdr );
say( wtr, "QUIT" ); hear( rdr );
if ( res != 250 )
throw new Exception( "Address is not valid!" );

valid = true;
rdr.close();
wtr.close();
skt.close();
}
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[] = {
"[email protected]",
"[email protected]",
"[email protected]", // Invalid domain name
"[email protected]", // Invalid address
"[email protected]" // Failure of this method
};

Lookup using MX record to validate mail server 652


Real's HowTo PDF version

for ( int ctr = 0 ; ctr < testData.length ; ctr++ ) {


System.out.println( testData[ ctr ] + " is valid? " +
isAddressValid( testData[ ctr ] ) );
}
return;
}
}

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 Description
211 System status, or system help reply.
214 Help message.
220 Domain service ready.
Ready to start TLS.
221 Domain service closing transmission channel.
250 OK, queuing for node node started.
Requested mail action okay, completed.
251 OK, no messages waiting for node node.
User not local, will forward to forwardpath.
252 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.
253 OK, messages pending messages for node node started.
354 Start mail input; end with ..
355 Octet-offset is the transaction offset.
421 Domain service not available, closing transmission channel.
432 A password transition is needed.
450 Requested mail action not taken: mailbox unavailable.
(ex. mailbox busy)
451 Requested action aborted: local error in processing.
Unable to process ATRN request now
452 Requested action not taken: insufficient system storage.
453 You have no mail.
454 TLS not available due to temporary reason.
Encryption required for requested authentication mechanism.
458 Unable to queue messages for node node.
459 Node node not allowed: reason.
500 Command not recognized: command.
Syntax error.
501 Syntax error, no parameters allowed.

Lookup using MX record to validate mail server 653


Real's HowTo PDF version

502 Command not implemented.


503 Bad sequence of commands.
504 Command parameter not implemented.
521 Machine does not accept mail.
530 Must issue a STARTTLS command first.
Encryption required for requested authentication mechanism.
534 Authentication mechanism is too weak.
538 Encryption required for requested authentication mechanism.
550 Requested action not taken: mailbox unavailable.
551 User not local; please try forwardpath.
552 Requested mail action aborted: exceeded storage allocation.
553 Requested action not taken: mailbox name not allowed.
554 Transaction failed.

RFC0821

Send an email using the SMTP protocol


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0079.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 [email protected]
//
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

Send an email using the SMTP protocol 654


Real's HowTo PDF version

(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: <[email protected]>");
send(in, out, "RCPT TO: " + recipient);
send(in, out, "DATA");
send(out, "Subject: In the ghetto");
send(out, "From: Elvis Presley <[email protected]>");
send (out, "\n");
// message body
send(out, "I'm alive. Help me!");
send(out, "\n.\n");
send(in, out, "QUIT");
s.close();
}
catch (Exception e) {
e.printStackTrace();
}
}

public void send(BufferedReader in, BufferedWriter out, String s) {


try {
out.write(s + "\n");
out.flush();
System.out.println(s);
s = in.readLine();
System.out.println(s);
}
catch (Exception e) {
e.printStackTrace();
}
}

public void send(BufferedWriter out, String s) {


try {
out.write(s + "\n");
out.flush();
System.out.println(s);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

Check if there is mail waiting


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0080.html

Check if there is mail waiting 655


Real's HowTo PDF version

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

Check if there is mail waiting 656


Real's HowTo PDF version

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

Receive email
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0081.html

import java.net.*;
import java.io.*;

public class DisplayMail {

public static void main(String arg[]) {


//
// usage :
// DisplayMail [mailServer] [user] [password]
// (will not delete mail on the server)
//
try {
// connect on port 110 (POP3)
System.out.println("Connect to " + arg[0] + ":110");
Socket s = new Socket(arg[0], 110);
BufferedReader in = new BufferedReader(
new InputStreamReader(s.getInputStream()));
BufferedWriter out = new BufferedWriter(
new OutputStreamWriter(s.getOutputStream()));
DisplayMail mail = new DisplayMail();
mail.login(in, out, arg[1], arg[2]);
int i = mail.check(in,out);
if (i==0) {
System.out.println("No mail waiting.");
}
else {
for (int j=1; j <= i; j++) {
String msg = mail.get(in, out, j);

Receive email 657


Real's HowTo PDF version

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)
&&(!(s.equals(".")))) {
t += s + "\n";
}
//
// To remove the mail on the server :
// send(out, "DELE "+i);
// receive(in);
//
return t;
}

private void send(BufferedWriter out, String s)


throws IOException {
System.out.println(s);
out.write(s+"\n");
out.flush();
}

private String receive(BufferedReader in)


throws IOException {
String s = in.readLine();
System.out.println(s);
return s;
}

private void login


(BufferedReader in, BufferedWriter out, String user, String pass)
throws IOException {
receive(in);

Receive email 658


Real's HowTo PDF version

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

Send email with an attachment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0083.html

In this example, Elvis is sending a GIF of his old Gumby friend. The attachment is encodded using the
BASE64 algorithm.

In this example, we are sending as attachment this image :

import java.io.*;
import java.net.*;

public class TestMailMIME {

Send email with an attachment 659


Real's HowTo PDF version

static int SMTPport = 25;


static Socket socket;
static DataInputStream in;
static DataOutputStream out;
static PrintStream prout;

/* Name of file to be sent. */


String FileName = "gumby.gif";

public static void main(String s[]) {


/*
** TestMailMIME [server] [recipient]
*/
TestMailMIME t = new TestMailMIME();
t.sendMail(s[0], s[1]);
}

public void sendMail(String mailServer, String recipient) {


System.out.println("Send mail with attached file ");
try {
Socket s = new Socket(mailServer, 25);
BufferedReader in = new BufferedReader
(new InputStreamReader(s.getInputStream(), "8859_1"));
BufferedWriter out = new BufferedWriter
(new OutputStreamWriter(s.getOutputStream(), "8859_1"));

String boundary = "DataSeparatorString";

// here you are supposed to send your username


sendln(in, out, "HELO theWorld");
// warning : some mail server validate the sender address
// in the MAIL FROM command, put your real address here
sendln(in, out, "MAIL FROM: ");
sendln(in, out, "RCPT TO: <" + recipient + ">" );
// to have more than one recipient, repeat
// sendln(in, out, "RCPT TO: <" + recipient2 + ">" );
// sendln(in, out, "RCPT TO: <" + recipient3 + ">" );
// etc...
// thanks to P-Y Colle for the tip!
sendln(in, out, "DATA");
sendln(out, "MIME-Version: 1.0");
sendln(out, "Subject: remember me");
sendln(out, "From: Elvis Presley <[email protected]>");
sendln
(out, "Content-Type: multipart/mixed; boundary=\"" + boundary +"\"");
sendln(out, "\r\n--" + boundary);

// Send the body


sendln(out, "Content-Type: text/plain; charset=\"us-ascii\"\r\n");
sendln(out, "I'm alive. Help me!\r\n\r\n");
sendln(out, "\r\n--" + boundary );

// send the GIF


sendln(out, "Content-Type:image/gif; name="+FileName);

Send email with an attachment 660


Real's HowTo PDF version

sendln
(out, "Content-Disposition: attachment;filename=\""+FileName+"\"");
sendln(out, "Content-transfer-encoding: base64\r\n");
MIMEBase64.encode(FileName, out);
sendln(out, "\r\n--" + boundary);

sendln(out, "\r\n\r\n--" + boundary + "--\r\n");


sendln(in, out,".");
sendln(in, out, "QUIT");
s.close();
}
catch (Exception e) {
e.printStackTrace();
}
}

public void sendln(BufferedReader in, BufferedWriter out, String s) {


try {
out.write(s + "\r\n");
out.flush();
// System.out.println(s);
s = in.readLine();
// System.out.println(s);
}
catch (Exception e) {
e.printStackTrace();
}
}

public void sendln(BufferedWriter out, String s) {


try {
out.write(s + "\r\n");
out.flush();
System.out.println(s);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

And the MIMEBase64 class

import java.io.*;

public class MIMEBase64 {


/*
Base64 uses a 65 character subset of US-ASCII,
allowing 6 bits for each character so the character
"m" with a Base64 value of 38, when represented
in binary form, is 100110.

With a text string, let's say "men" is encoded this


is what happens :

Send email with an attachment 661


Real's HowTo PDF version

The text string is converted into its US-ASCII value.

The character "m" has the decimal value of 109


The character "e" has the decimal value of 101
The character "n" has the decimal value of 110

When converted to binary the string looks like this :

m 01101101
e 01100101
n 01101110

These three "8-bits" are concatenated to make a


24 bit stream
011011010110010101101110

This 24 bit stream is then split up into 4 6-bit


sections
011011 010110 010101 101110

We now have 4 values. These binary values are


converted to decimal form
27 22 21 46

And the corresponding Base64 character are :


b W V u

The encoding is always on a three characters basis


(to have a set of 4 Base64 characters). To encode one
or two then, we use the special character "=" to pad
until 4 base64 characters is reached.

ex. encode "me"

01101101 01100101
0110110101100101
011011 010110 0101
111111 (AND to fill the missing bits)
011011 010110 010100
b W U
b W U = ("=" is the padding character)

so "bWU=" is the base64 equivalent.

encode "m"

01101101
011011 01
111111 (AND to fill the missing bits)
011011 010000
b Q = = (two paddings are added)

Finally, MIME specifies that lines are 76 characters wide maximum.

Send email with an attachment 662


Real's HowTo PDF version

*/

static String BaseTable[] = {


"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P",
"Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f",
"g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v",
"w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/"
};

public static void encode(String filename, BufferedWriter out) {


try {
File f = new File(filename);
FileInputStream fin = new FileInputStream(filename);

// read the entire file into the byte array


byte bytes[] = new byte[(int)(f.length())];
int n = fin.read(bytes);

if (n < 1) return; // no bytes to encode!?!

byte buf[] = new byte[4]; // array of base64 characters

int n3byt = n / 3; // how 3 bytes groups?


int nrest = n % 3; // the remaining bytes from the grouping
int k = n3byt * 3; // we are doing 3 bytes at a time
int linelength = 0; // current linelength
int i = 0; // index

// do the 3-bytes groups ...


while ( i < k ) {
buf[0] = (byte)(( bytes[i] & 0xFC) >> 2);
buf[1] = (byte)(((bytes[i] & 0x03) << 4) |
((bytes[i+1] & 0xF0) >> 4));
buf[2] = (byte)(((bytes[i+1] & 0x0F) << 2) |
((bytes[i+2] & 0xC0) >> 6));
buf[3] = (byte)( bytes[i+2] & 0x3F);
send(out, BaseTable[buf[0]]);
send(out, BaseTable[buf[1]]);
send(out, BaseTable[buf[2]]);
send(out, BaseTable[buf[3]]);
/*
The above code can be written in more "optimized"
way. Harder to understand but more compact.
Thanks to J. Tordera for the tip!
buf[0]= (byte)(b[i] >> 2);
buf[1]= (byte)(((b[i] & 0x03) << 4)|(b[i+1]>> 4));
buf[2]= (byte)(((b[i+1] & 0x0F)<< 2)|(b[i+2]>> 6));
buf[3]= (byte)(b[i+2] & 0x3F);
send(out,BaseTable[buf[0]]+BaseTable[buf[1]]+
BaseTable[buf[2]]+BaseTable[buf[3]]);
*/

if ((linelength += 4) >= 76) {

Send email with an attachment 663


Real's HowTo PDF version

send(out, "\r\n");
linelength = 0;
}
i += 3;
}

// deals with with the padding ...


if (nrest==2) {
// 2 bytes left
buf[0] = (byte)(( bytes[k] & 0xFC) >> 2);
buf[1] = (byte)(((bytes[k] & 0x03) << 4) |
((bytes[k+1] & 0xF0) >> 4));
buf[2] = (byte)(( bytes[k+1] & 0x0F) << 2);
}
else if (nrest==1) {
// 1 byte left
buf[0] = (byte)((bytes[k] & 0xFC) >> 2);
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

Send email with an attachment 664


Real's HowTo PDF version

...

/* Name of files to be sent. */


String FileName1 = "gumby.gif";
String FileName2 = "gumby.txt";

...

public void sendMail(String mailServer, String recipient) {


System.out.println("Send mail with attached file");
try {
Socket s = new Socket(mailServer, 25);
BufferedReader in = new BufferedReader
(new InputStreamReader(s.getInputStream(), "8859_1"));
BufferedWriter out = new BufferedWriter
(new OutputStreamWriter(s.getOutputStream(), "8859_1"));

String boundary = "DataSeparatorString";

// here you are supposed to send your username


sendln(in, out, "HELO world");
sendln(in, out, "MAIL FROM: <[email protected]>");
sendln(in, out, "RCPT TO: <" + recipient + ">" );
sendln(in, out, "DATA");
sendln(out, "MIME-Version: 1.0");
sendln(out, "Subject: remember me");
sendln(out, "From: Elvis Presley <[email protected]<");
sendln
(out,"Content-Type: multipart/mixed; boundary=\"" + boundary +"\"");
sendln(out, "\r\n--" + boundary);

// send the GIF


sendln(out, "Content-Type: text/plain; charset=\"us-ascii\"\r\n");
sendln(out, "I'm alive. Help me!\n\n");
sendln(out, "\r\n" + "--" + boundary );
sendln(out, "Content-Type:image/gif; name="+FileName1);
sendln
(out, "Content-Disposition: attachment;filename=\""+FileName1+"\"");
sendln(out, "Content-transfer-encoding: base64\r\n");
MIMEBase64.encode(FileName1, out);
sendln(out, "\r\n--" + boundary);

// the text file


sendln(out, "Content-Type: text/plain; name="+FileName2);
sendln(out, "Content-Disposition: inline;filename=\""+FileName2+"\"");
// to send the file as an attachment instead of "inline" use :
// sendln
// (out, "Content-Type: text/plain; name="+FileName2);
// sendln
// (out,"Content-Disposition: attachment;filename=\""+FileName2+"\"");
sendln(out, "Content-Transfer-Encoding: base64\r\n");
MIMEBase64.encode(FileName2, out);
sendln(out, "\r\n\r\n--" + boundary + "--\r\n");

Send email with an attachment 665


Real's HowTo PDF version

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

Send email with JavaMail


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0321.html

The JavaMail API can found here.


You need 2 jars : mail.jar and activation.jar.
It's a good idea to read the JavaMail FAQ.

Simple email

import javax.mail.*;
import javax.mail.internet.*;

import java.util.Properties;

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("[email protected]"));

transport.connect();
transport.sendMessage(message,

Send email with JavaMail 666


Real's HowTo PDF version

message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

HTML Email
import javax.mail.*;
import javax.mail.internet.*;

import java.util.Properties;

class SimpleHTMLMail {
public static void main(String[] args) throws Exception{
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.host", "mymail.server.org");
props.setProperty("mail.user", "emailuser");
props.setProperty("mail.password", "");

Session mailSession = Session.getDefaultInstance(props, null);


Transport transport = mailSession.getTransport();

MimeMessage message = new MimeMessage(mailSession);


message.setSubject("Testing javamail html");
message.setContent
("This is a test <b>HOWTO<b>", "text/html; charset=ISO-8859-1");
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("[email protected]"));

transport.connect();
transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

Email with attachment


import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.FileDataSource;
import javax.activation.DataHandler;

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

Send email with JavaMail 667


Real's HowTo PDF version

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("[email protected]"));

transport.connect();
transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

Send email with authentication (JavaMail)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0538.html

import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;

import java.util.Properties;

public class SimpleMail {

private static final String SMTP_HOST_NAME = "smtp.myserver.com";


private static final String SMTP_AUTH_USER = "myusername";
private static final String SMTP_AUTH_PWD = "mypwd";

Send email with authentication (JavaMail) 668


Real's HowTo PDF version

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("[email protected]"));
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("[email protected]"));

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.

HTML mail with images (JavaMail)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0504.html

It's easy to send HTML mail with JavaMail. Simply set the content type to "text/html".

import javax.mail.*;
import javax.mail.internet.*;

HTML mail with images (JavaMail) 669


Real's HowTo PDF version

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("[email protected]"));
message.setContent("<h1>Hello world</h1>", "text/html");
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("[email protected]"));

transport.connect();
transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

One approach to include images in the mail body is to use the IMG tag and make the images available on a
server.

import javax.mail.*;
import javax.mail.internet.*;

import java.util.Properties;

class SimpleMail1 {
public static void main(String[] args) throws Exception{
System.out.println("Sending mail...");
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.host", "smtp.mymailserver.com");
props.setProperty("mail.user", "myuser");
props.setProperty("mail.password", "mypwd");

Session mailSession = Session.getDefaultInstance(props, null);


mailSession.setDebug(true);
Transport transport = mailSession.getTransport();

MimeMessage message = new MimeMessage(mailSession);


message.setSubject("HTML mail with images");
message.setFrom(new InternetAddress("[email protected]"));
message.setContent

HTML mail with images (JavaMail) 670


Real's HowTo PDF version

("<h1>This is a test</h1>"
+ "<img src=\"http://www.rgagnon.com/images/jht.gif\">",
"text/html");
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("[email protected]"));

transport.connect();
transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

The browser accesses these images just as if it were displaying an image in a Web page. Unfortunately,
spammers have used this mechanism as a sneaky way to record who visits their site (and mark your email
as valid). To protect your privacy, many Web-based (and other) email clients don't display images in
HTML emails.

An alternative to placing absolute URLs to images in your HTML is to include the images as attachments
to the email. The HTML can reference the image in an attachment by using the protocol prefix cid: plus the
content-id of the attachment.

import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;

import java.util.Properties;

class SimpleMail2 {
public static void main(String[] args) throws Exception{
System.out.println("Sending mail...");
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.host", "smtp.mymailserver.com");
props.setProperty("mail.user", "myuser");
props.setProperty("mail.password", "mypwd");

Session mailSession = Session.getDefaultInstance(props, null);


mailSession.setDebug(true);
Transport transport = mailSession.getTransport();

MimeMessage message = new MimeMessage(mailSession);


message.setSubject("HTML mail with images");
message.setFrom(new InternetAddress("[email protected]"));
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("[email protected]"));

//
// This HTML mail have to 2 part, the BODY and the embedded image
//
MimeMultipart multipart = new MimeMultipart("related");

HTML mail with images (JavaMail) 671


Real's HowTo PDF version

// 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("Content-ID","<image>");

// add it
multipart.addBodyPart(messageBodyPart);

// put everything together


message.setContent(multipart);

transport.connect();
transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

Debug a Javamail Program


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0552.html

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

Debug a Javamail Program 672


Real's HowTo PDF version

• link a PrintStream to a ByteArrayOutputStream,


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

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.

Use a JavaMail server mock-up to act as "in-memory" mail server

See https://java.net/projects/mock-javamail and http://quintanasoft.com/dumbster/. These mock-ups are


designed to act a mail server but the actual email is not delivered to the mail recipient which can be useful
in a testing stage.

Send email with SMTPS (eg. Google GMail) (Javamail)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0570.html

Debug a Javamail Program 673


Real's HowTo PDF version

It's not uncommon that the outgoing mail needs to be encrypted using the SMTPS protocol.

It's the case for GMail for example.

You need Javamail 1.4 to use the SMTPS protocol.

import javax.mail.*;
import javax.mail.internet.*;

import java.util.Properties;

public class SimpleSSLMail {

private static final String SMTP_HOST_NAME = "smtp.gmail.com";


private static final int SMTP_HOST_PORT = 465;
private static final String SMTP_AUTH_USER = "[email protected]";
private static final String SMTP_AUTH_PWD = "mypwd";

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


new SimpleSSLMail().test();
}

public void test() throws Exception{


Properties props = new Properties();

props.put("mail.transport.protocol", "smtps");
props.put("mail.smtps.host", SMTP_HOST_NAME);
props.put("mail.smtps.auth", "true");
// props.put("mail.smtps.quitwait", "false");

Session mailSession = Session.getDefaultInstance(props);


mailSession.setDebug(true);
Transport transport = mailSession.getTransport();

MimeMessage message = new MimeMessage(mailSession);


message.setSubject("Testing SMTP-SSL");
message.setContent("This is a test", "text/plain");

message.addRecipient(Message.RecipientType.TO,
new InternetAddress("[email protected]"));

transport.connect
(SMTP_HOST_NAME, SMTP_HOST_PORT, SMTP_AUTH_USER, SMTP_AUTH_PWD);

transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

Send email with SMTPS (eg. Google GMail) (Javamail) 674


Real's HowTo PDF version

Even you send to correct credentials, it's possible that you get the
javax.mail.AuthenticationFailedException exception from Gmail. If it's the case, you may need to explicitly
enable "less secure apps" setting in your Gmail account, see
https://support.google.com/accounts/answer/6010255>Answer from Google.

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)

Mix plain text and HTML content in a mail


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0471.html

Properties props = new Properties();


props.put("mail.smtp.host", "MYMAILSERVER");
Session session = Session.getInstance(props,null);
MimeMessage message = new MimeMessage(session);

InternetAddress from = new InternetAddress("[email protected]");


InternetAddress to = new InternetAddress("[email protected]");

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");
multipart.addBodyPart(messageBodyPart);

message.setContent(multipart);
Transport.send(message);

Send email with SMTPS (eg. Google GMail) (Javamail) 675


Real's HowTo PDF version

Read an Outlook MSG file (OpenSource packages)


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

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 java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import 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 poi-scratchpad-3.6 and poi-3.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);

Read an Outlook MSG file (OpenSource packages) 676


Real's HowTo PDF version

// 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 java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.Map;

import org.apache.poi.hdgf.chunks.Chunk;
import org.apache.poi.hsmf.MAPIMessage;
import org.apache.poi.hsmf.datatypes.AttachmentChunks;
import org.apache.poi.hsmf.datatypes.Chunks;
import org.apache.poi.hsmf.exceptions.ChunkNotFoundException;

// You need poi-scratchpad-3.7 and poi-3.7 ( http://poi.apache.org/ )


public class DetectMSGAttachment {
public static void main (String ... args) throws IOException {

Read an Outlook MSG file (OpenSource packages) 677


Real's HowTo PDF version

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

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 {

Read an Outlook MSG file (OpenSource packages) 678


Real's HowTo PDF version

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


MsgParser msgp = new MsgParser();
Message msg = msgp.parseMsg("c:/temp/test2.msg");

String fromEmail = msg.getFromEmail();


String fromName = msg.getFromName();
String subject = msg.getSubject();
String 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();
}
}
}
}

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

Handle EML file with JavaMail


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0458.html

Loading an .EML file

When saving an email to a file, the resulting file has an eml extension (email files--which are in RFC 822
format). This kind of file can be read and parsed by JavaMail.

import java.util.*;
import java.io.*;

Read an Outlook MSG file (OpenSource packages) 679


Real's HowTo PDF version

import javax.mail.*;
import javax.mail.internet.*;

public class ReadEmail {

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


display(new File("C:\\temp\\message.eml"));

public static void display(File emlFile) throws Exception{


Properties props = System.getProperties();
props.put("mail.host", "smtp.dummydomain.com");
props.put("mail.transport.protocol", "smtp");

Session mailSession = Session.getDefaultInstance(props, null);


InputStream source = new FileInputStream(emlFile);
MimeMessage message = new MimeMessage(mailSession, source);

System.out.println("Subject : " + message.getSubject());


System.out.println("From : " + message.getFrom()[0]);
System.out.println("--------------");
System.out.println("Body : " + message.getContent());
}
}

A typical eml looks like this :

X-Mozilla-Status: 0001
X-Mozilla-Status2: 00000000
Received: from tomts25-srv.bellnexxia.net
(tomts25.bellnexxia.net [209.226.175.188])
by tactika.com (8.9.3/8.9.3) with ESMTP id NAA07621
for <[email protected]>; Sun, 1 Feb 2004 13:25:33 -0500 (EST)
Date: Sun, 01 Feb 2004 13:31:40 -0500
From: real gagnon <[email protected]>
Reply-To: [email protected]
User-Agent: Mozilla/5.0
(Windows; U; Windows NT 5.1; en-US; rv:1.4)
Gecko/20030624 Netscape/7.1 (ax)
X-Accept-Language: en-us, en
MIME-Version: 1.0
To: [email protected]
Subject: Example for HowTo
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
X-UIDL: oP#!!c]^!!1;-!!T@1"!

This is an example for HowTo

Handle EML file with JavaMail 680


Real's HowTo PDF version

Running the above HowTo gives this output :

Subject : Example for HowTo


From : real gagnon <[email protected]>
--------------
Body :
This is an example for HowTo

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

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("[:\\\\/*?|<> \"]", "_");
}

Receive email (and attachment) using IMAP


Current version of this HowTo :

Handle EML file with JavaMail 681


Real's HowTo PDF version

http://www.rgagnon.com/javadetails/../javadetails/java-receive-email-using-imap.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 java.io.*;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;

public class ReceiveMailImap {

public ReceiveMailImap() {}

//
// inspired by :
// http://www.mikedesjardins.net/content/2008/03/using-javamail-to-read-and-extract/
//

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","[email protected]", "******");
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());

Receive email (and attachment) using IMAP 682


Real's HowTo PDF version

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

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) {
// part-within-a-part, do some recursion...
saveParts(part.getContent(), filename);
}
else {
String extension = "";
if (part.isMimeType("text/html")) {
extension = "html";
}

Receive email (and attachment) using IMAP 683


Real's HowTo PDF version

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.

Receive email (and attachment) using POP3


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-receive-email-using-pop3.html

POP3 supports simple download-and-delete 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.*;

Receive email (and attachment) using POP3 684


Real's HowTo PDF version

import javax.mail.*;

import javax.mail.internet.MimeBodyPart;

public class ReceiveMailPOP3 {


private static final String HOST = "pop.gmail.com";
private static final String USERNAME = "[email protected]";
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(); }
}
}

public static void saveParts(Object content, String filename)


throws IOException, MessagingException
{
OutputStream out = null;
InputStream in = null;
try {

Receive email (and attachment) using POP3 685


Real's HowTo PDF version

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) {
// part-within-a-part, 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.

Debug a HttpURLConnection problem


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-debug-HttpURLConnection-problem.html

Debug a HttpURLConnection problem 686


Real's HowTo PDF version

Take this example.

import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;

public class HttpConnect {


public static void main(String[] args) throws Exception {
URL url = new URL("http://www.rgagnon.com/howto.html");
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);
}
}
}

This above snippet reads the HTML page and dumps it to the console.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/lo


<HTML><HEAD>
<!-- developpe par Real Gagnon, Quebec Canada -->
<LINK REL="SHORTCUT ICON" HREF="http://www.rgagnon.com/favicon.ico">
<META NAME="description"
Content="Real's JAVA JAVASCRIPT WSH and PowerBuilder How-to pages with useful code snip
<META NAME="keywords"
Content="java,javascript,wsh,vbscript,how-to,powerbuilder">
<LINK title="mystyle" href="howto.css" type="text/css" rel="stylesheet">
...

To trace what is going on at the HTTP protocol level, we can switch the
HttpURLConnection/UrlConnection in debug mode.

You must enable the java-logging mechanism by setting a special property when starting the JVM :

java.exe -Djava.util.logging.config.file=logging.properties HttpConnect

and put in logging.properties file (by default in JRE_HOME\lib) the following property

sun.net.www.protocol.http.HttpURLConnection.level = ALL

Note :
If running from Eclipse, you put the -Djava.util.logging... via the Run configuration dialog -> Arguments
Tab -> VM arguments textarea.

Debug a HttpURLConnection problem 687


Real's HowTo PDF version

The result is :

2010-08-07 00:00:31 sun.net.www.protocol.http.HttpURLConnection writeRequests


FIN: sun.net.www.MessageHeader@16caf435 pairs: {GET /howto.html HTTP/1.1: null}{User-Agent: J
2010-08-07 00:00:31 sun.net.www.protocol.http.HttpURLConnection getInputStream
FIN: sun.net.www.MessageHeader@5ac0728 pairs: {null: HTTP/1.1 200 OK}{Date: Sat, 07 Aug 2010
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/lo
<HTML><HEAD>
<!-- developpe par Real Gagnon, Quebec Canada -->
<LINK REL="SHORTCUT ICON" HREF="http://www.rgagnon.com/favicon.ico">
<META NAME="description"
Content="Real's JAVA JAVASCRIPT WSH and PowerBuilder How-to pages with useful code snip
...

Check if a file was modified on the server


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0069.html

URL u =null;

long timestamp = 0;

try {
u = new URL(getDocumentBase(), "test.gif");
URLConnection uc = u.openConnection();
uc.setUseCaches(false);
/*
** use timestamp has a reference, re-open an URLConnection
** to the same file to check if the timestamp is different
** with the getLastModified() method.
*/
timestamp = uc.getLastModified();
}
catch (Exception e) {
e.printStackTrace();
}
}

Check if a page exists


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0059.html

[JDK1.1]

import java.net.*;

Check if a file was modified on the server 688


Real's HowTo PDF version

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

Check if a page exists 689


Real's HowTo PDF version

URL u = new URL(URLName);


HttpURLConnection con = (HttpURLConnection) u.openConnection();
//
// it's not the greatest idea to use a sun.misc.* class
// Sun strongly advises not to use them since they can
// change or go away in a future release so beware.
//
sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
String encodedUserPwd =
encoder.encode("domain\\username:password".getBytes());
con.setRequestProperty
("Proxy-Authorization", "Basic " + encodedUserPwd);
con.setRequestMethod("HEAD");
System.out.println
(con.getResponseCode() + " : " + con.getResponseMessage());
return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}
}

Connect through a Proxy


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0085.html

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

Connect through a Proxy 690


Real's HowTo PDF version

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

Connect through a Proxy 691


Real's HowTo PDF version

Proxy and Username/Password

You might need to identify yourself to the proxy server.

One way is to use the HTTP property "Proxy-Authorization" with a username:password base64 encoded.

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("Proxy-Authorization", "Basic " + encoded);
uc.connect();

NOTE: For a base64 function, see this How-to.

The following example dumps the content of a URL but before we identify ourself to the proxy.
import java.net.*;
import java.io.*;

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
("Proxy-Authorization", "Basic " + encodedUserPwd);
// PROXY ----------

Connect through a Proxy 692


Real's HowTo PDF version

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

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

Connect through a Proxy 693


Real's HowTo PDF version

Identify yourself using HTTP Authentification


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0084.html

import java.net.*;
import java.io.*;

public class TestAuth {

public static void main (String args[]){


/*
** args[0] is the URL protected
** args[1] is the username
** args[2] is the password
*/
try {
BufferedReader in = new BufferedReader(
new InputStreamReader
(openURLForInput(new URL(args[0]), args[1], args[2])));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
}
catch (IOException e) {
e.printStackTrace();
}
}

public static InputStream openURLForInput


(URL url, String uname, String pword)
throws IOException
{
URLConnection conn = url.openConnection();
conn.setDoInput (true);
conn.setRequestProperty ("Authorization",
userNamePasswordBase64(uname,pword));
conn.connect ();
return conn.getInputStream();
}

public static String userNamePasswordBase64


(String username, String password)
{
return "Basic " + base64Encode (username + ":" + password);
}

private final static char base64Array [] = {

Identify yourself using HTTP Authentification 694


Real's HowTo PDF version

'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',


'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'
};

private static String base64Encode (String string) {


String encodedString = "";
byte bytes [] = string.getBytes ();
int i = 0;
int pad = 0;
while (i < bytes.length) {
byte b1 = bytes [i++];
byte b2;
byte b3;
if (i >= bytes.length) {
b2 = 0;
b3 = 0;
pad = 2;
}
else {
b2 = bytes [i++];
if (i >= bytes.length) {
b3 = 0;
pad = 1;
}
else
b3 = bytes [i++];
}
byte c1 = (byte)(b1 >> 2);
byte c2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
byte c3 = (byte)(((b2 & 0xf) << 2) | (b3 >> 6));
byte c4 = (byte)(b3 & 0x3f);
encodedString += base64Array [c1];
encodedString += base64Array [c2];
switch (pad) {
case 0:
encodedString += base64Array [c3];
encodedString += base64Array [c4];
break;
case 1:
encodedString += base64Array [c3];
encodedString += "=";
break;
case 2:
encodedString += "==";
break;
}

Identify yourself using HTTP Authentification 695


Real's HowTo PDF version

}
return encodedString;
}
}

A better alternative is the Authenticator class, see this HowTo.

NOTE: a simple explanation about the base64 encoding principle is shown in this How-to.

An alternative way to Base64 encoding is to use the Base64 class in the sun.misc.* package.

sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();


String encodedUserPwd =
encoder.encode("domain\\username:password".getBytes());
con.setRequestProperty("Proxy-Authorization", "Basic " + encodedUserPwd);

Use of the sun.* package is "discouraged" by sun and not formally supported. Those classes can be missing
in your JDK release.

Check this HowTo for a more official way to encode/decode to/from Base64.

Talk to a CGI/Servlet
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0082.html

From the client point of view, there is no difference talking to CGI or Servlet. There is two ways to send a
request to a CGI. The GET method contains encoded parameters in the URL. A typical URL talking to CGI
using the GET method would be:

new URL("http://www.server.com/cgi-bin/acgi.pl?name=real&site=java+howto");

Here we calling a script called aCGI.pl (a PERL script) passing the parameters name and site. Parameters
are encoded, spaces are changed to "+" and special character to hexadecimal using a 3-letter escape
sequence. Each parameter is delimited by the character "&". Habitually the encoding is done through the
static method encode of the java.net.URLencoder class.

String theCGI = "http://www.server.com/cgi-bin/aCGI.pl?";


String encoded = "name=" + URLencoder.encode("Real Gagnon");
URL cgiurl = new URL(thecgi + encoded);

Once the URL is constructed, you call the CGI using the showDocument method (Applet).

getAppletContext().showDocument(cgiurl);

The CGI will process the result and produce a page to be displayed.

Talk to a CGI/Servlet 696


Real's HowTo PDF version

The POST method allows the programmer to manipulate the data received from the CGI. First a connection
is made to the CGI, an OutputStream is open to send the parameters (if any). Then InputStream is created to
receive the result.

String theCGI = "http://www.server.com/cgi-bin/aCGI.pl";


String encoded = "name=" + URLencoder.encode("Real Gagnon");
URL CGIurl = new URL(theCGI);

URLConnection c = CGIurl.openConnection();
c.setDoOutput(true);
c.setUseCaches(false);
c.setRequestProperty("content-type","application/x-www-form-urlencoded");
DataOutputStream out = new DataOutputStream(c.getOutputStream());
out.writeBytes(encoded);
out.flush(); out.close();

BufferedReader in =
new BufferedReader(new InputStreamReader(c.getInputStream());

String aLine;
while ((aLine = in.readLine()) != null) {
// data from the CGI
System.out.println(aLine);
}

You can't do some output then some input and do again some output. You must do all the output and then
the input. There is no "dialog" between the client and the server. The client make a request and the server
send back the result and close the connection.

Write/Read cookies using HTTP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0092.html

For a Java-Javascript solution, check this How-to.

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

class CookiesInJava {
static Hashtable theCookies = new Hashtable();
/**
* Send the Hashtable (theCookies) as cookies, and write them to
* the specified URLconnection
*
* @param urlConn The connection to write the cookies to.
* @param printCookies Print or not the action taken.
*

Write/Read cookies using HTTP 697


Real's HowTo PDF version

* @return The urlConn with the all the cookies in it.


*/
public URLConnection writeCookies
(URLConnection urlConn, boolean printCookies){
String cookieString = "";
Enumeration keys = theCookies.keys();
while (keys.hasMoreElements()) {
String key = (String)keys.nextElement();
cookieString += key + "=" + theCookies.get(key);
if (keys.hasMoreElements())
cookieString += "; ";
}
urlConn.setRequestProperty("Cookie", cookieString);
if (printCookies)
System.out.println("Wrote cookies:\n " + cookieString);
return urlConn;
}

/**
* Read cookies from a specified URLConnection, and insert them
* to the Hashtable
* The hashtable represents the Cookies.
*
* @param urlConn the connection to read from
* @param printCookies Print the cookies or not, for debugging
* @param reset Clean the Hashtable or not
*/
public void readCookies(URLConnection urlConn, boolean printCookies,
boolean reset){
if (reset)
theCookies.clear();
int i=1;
String hdrKey;
String hdrString;
String aCookie;
while ((hdrKey = urlConn.getHeaderFieldKey(i)) != null) {
if (hdrKey.equals("Set-Cookie")) {
hdrString = urlConn.getHeaderField(i);
StringTokenizer st = new StringTokenizer(hdrString,",");
while (st.hasMoreTokens()) {
String s = st.nextToken();
aCookie = s.substring(0, s.indexOf(";"));
// aCookie = hdrString.substring(0, s.indexOf(";"));
int j = aCookie.indexOf("=");
if (j != -1) {
if (!theCookies.containsKey(aCookie.substring(0, j))){
// if the Cookie do not already exist then when keep it,
// you may want to add some logic to update
// the stored Cookie instead. thanks to rwhelan
theCookies.put
(aCookie.substring(0, j),aCookie.substring(j + 1));
if (printCookies){
System.out.println("Reading Key: "
+ aCookie.substring(0, j));

Write/Read cookies using HTTP 698


Real's HowTo PDF version

System.out.println(" Val: "


+ aCookie.substring(j + 1));
}
}
}
}
}
i++;
}
}

/**
* Display all the cookies currently in the HashTable
*
*/
public void viewAllCookies() {
System.out.println("All Cookies are:");
Enumeration keys = theCookies.keys();
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);
}
}

Write/Read cookies using HTTP 699


Real's HowTo PDF version

}
}

Thanks to Saar Machtiner for the bug fix

Read a text file from the internet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-read-a-file-from-the-internet.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));
}
}

Read a GIF or CLASS from an URL save it locally


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0060.html

import java.io.*;
import java.net.*;

public class SuckURL {


String aFile;
String aURL;

public static void main(String args[]) {


// GIF JAVA How-to at Real's Home
String url =
"http://www.rgagnon.com/images/";

Read a text file from the internet 700


Real's HowTo PDF version

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

Read a GIF or CLASS from an URL save it locally 701


Real's HowTo PDF version

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=1-26-57436-1.

Resolve a relative URL


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0297.html

import java.net.URL;

public class ResolveRelativeURL {


public static void main (String[] args) throws
java.net.MalformedURLException {
URL relativeURL, baseURL;
baseURL = new URL ("http://www.rgagnon.com/");
relativeURL = new URL ( baseURL, "./javadetails/java-0001.html");
System.out.println ( relativeURL.toExternalForm ());
/*
output :
http://www.rgagnon.com/javadetails/java-0001.html
*/
}
}

File Size from URL


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0298.html

import java.io.*;

Resolve a relative URL 702


Real's HowTo PDF version

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

Using HTTPS protocol


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0308.html

For Applets, both IE and NN have implemented https in their java.net.URL class so just use it exactly as
you would for a regular http URL.

URL ssl = new URL("https://www.secureserver.com);


InputStream is = ssl.openStream();

For application, take a look at the Sun's Secure Socket Extension (JSSE).

Before connecting with a secure URL, we must do this first :

java.security.Security.addProvider(new
com.sun.net.ssl.internal.ssl.Provider());

System.setProperty
("java.protocol.handler.pkgs",
"com.sun.net.ssl.internal.www.protocol");

File Size from URL 703


Real's HowTo PDF version

A useful link for that is this JavaWorld's Tip

Since JDK 1.4, the JSSE package is included so you don't have to add anything special. However you may
need to import the certificate from the host (that is the server that you are connecting to using the https:
protocol). One easy way to do this is to open a secured page (say https://mysecuredhost.com) with IE, click
on the SSL-symbol (bottom right) and exported the key into the file "c:\cacerts.ce". Go in
"%java_home%\bin" and type this:

keytool -import -v -alias meincert -trustcacerts -file c:\

Fix certificate problem in HTTPS


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-fix-certificate-problem-in-HTTPS.html

HTTPS protocol is supported since JDK1.4 (AFAIK), you have nothing special to do.

import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import 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 self-signed 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.

Using HTTPS protocol 704


Real's HowTo PDF version

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.java-samples.com/showtutorial.php?tutorialid=210

Or you can override the check and accept an untrusted certificate (with the risk coming with it!).

import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import 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[] {
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 all-trusting host name verifier


HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier

Fix certificate problem in HTTPS 705


Real's HowTo PDF version

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

Fetch a page from Google


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0399.html

You can't directly fetch a page from Google because a check is made (by Google) to restrict access to "real"
browser so a "403" HTTP code is returned to your Java program.

You need to fool Google by pretending to be a legitimate browser.

String search= "What you want to search for";


String google="http://www.google.ca/search?q="
+ search + "&hl=en&ie=UTF-8&oe=UTF8";

URL urlObject = new URL(google);


URLConnection con = urlObject.openConnection();
con.setRequestProperty
( "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" );
webData = new BufferedReader(new InputStreamReader(con.getInputStream()));
...

Note : You may want to take a look at http://www.google.com/apis/ to learn how to interact with Google
via the official API's.

As seen above, you can directly override the HTTP header. Another way is to start the program with a
modified System.property http.agent.

>java
"-Dhttp.agent=Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" MyClass

Fetch a page from Google 706


Real's HowTo PDF version

or in your program

System.setProperty
("http.agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");

Upload a file
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0543.html

To upload a file to a server you need something on the server side to accept the file, you can't do it with
client-side code only. A simple way to use the HTML tag in a FORM

<FORM METHOD=POST ENCTYPE="multipart/form-data" ACTION="../myuploadscript">


File to upload: <INPUT TYPE=FILE NAME="upfile"><
<INPUT TYPE=SUBMIT VALUE="Submit">
</FORM>

which looks like

File to upload:

The associated FORM target is a script on the server side that can handle HTTP file upload. Typically in
Java, it's a servlet.

The 2 most popular Java packages (server-side) to handle file upload are :
• Jakarta Commons File Upload
• O'reilly MultipartRequest (com.oreilly.servlet)

On the client side, a java application can use Jakarta Commons HTTP client to initiate a file upload.

Postlet is a Java applet used to enable websites to allow their users to send multiple files to a webserver
with a few simple clicks. Postlet is useable with any server side scripting language that is capable of
handling file uploads.

Remove HTML tags from a file to extract only the TEXT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0424.html

Upload a file 707


Real's HowTo PDF version

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("java-new.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.

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 java.io.IOException;
import java.io.FileReader;
import java.io.Reader;
import java.util.List;
import java.util.ArrayList;

import javax.swing.text.html.parser.ParserDelegator;
import javax.swing.text.html.HTMLEditorKit.ParserCallback;
import javax.swing.text.html.HTML.Tag;
import 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));

Remove HTML tags from a file to extract only the TEXT 708
Real's HowTo PDF version

}
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("java-new.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 well-formed.

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

Remove HTML tags from a file to extract only the TEXT 709
Real's HowTo PDF version

("C:/RealHowTo/topics/java-language.html");
System.out.println(HTMLUtils.extractText(reader));
}
}

Using Apache Tika

Apache Tika

import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.BodyContentHandler;
import org.xml.sax.ContentHandler;

public class ParseHTMLWithTika {


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

InputStream is = null;
try {

is = new FileInputStream("C:/Temp/java-x.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

Extract links from an HTML page


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0639.html

Remove HTML tags from a file to extract only the TEXT 710
Real's HowTo PDF version

Using javax.swing.text.html.HTMLEditorKit

import java.io.IOException;
import java.io.FileReader;
import java.io.Reader;
import java.util.List;
import java.util.ArrayList;

import javax.swing.text.html.parser.ParserDelegator;
import javax.swing.text.html.HTMLEditorKit.ParserCallback;
import javax.swing.text.html.HTML.Tag;
import javax.swing.text.html.HTML.Attribute;
import 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("java-new.html");
List<String> links = HTMLUtils.extractLinks(reader);
for (String link : links) {
System.out.println(link);
}
}
}

Using an HTML parser

In this HowTo, I will use the OpenSource package Jsoup.

import java.io.IOException;
import java.util.List;

Extract links from an HTML page 711


Real's HowTo PDF version

import java.util.ArrayList;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import 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/java-language.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.

Call a web service (generated with BEA ServiceGen)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0657.html

Call a web service (generated with BEA ServiceGen) 712


Real's HowTo PDF version

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 :
Content-Length: [459]
SOAPAction: [""]
Content-Type: [text/xml; charset=utf-8]

<?xml version="1.0" encoding="utf-8" standalone="yes"?>


<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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=Microsoft-IIS/6.0
X-Powered-By=Servlet/2.5 JSP/2.1
Cache-Control=no-cache="set-cookie"
Content-Length=1211
Content-Type=text/xml; charset=ISO-8859-1

Call a web service (generated with BEA ServiceGen) 713


Real's HowTo PDF version

Set-Cookie=JSESSIONID=BJYXKJqfFC7nl9TMgYkJg9DpL5kZ1nTQy2M8v1BXJnT1R8n1DhfX!-1553076658; pat

Envelope :
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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: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:[email protected]/commonWS/commonwebservices?WSDL";

Do basic authentication when calling a webservice


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-do-basic-authentication-when-calling-a-webservice.html

You have a web service, generated with JAX-WS 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 {

Do basic authentication when calling a webservice 714


Real's HowTo PDF version

private String user;


private String password;

public MyAuthenticator(String user,String password) {


this.user = user;
this.password = password;
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
PasswordAuthentication auth = new PasswordAuthentication(user,password.toCharArray())
return auth;
}
}

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

Have a simple HTTP server


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-have-a-simple-http-server.html

Since Java 1.6, there's a built-in HTTP server included with the JDK.

Do basic authentication when calling a webservice 715


Real's HowTo PDF version

The HttpServer provides a simple high-level 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;
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 java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.Headers;

public class SimpleHttpServer {

Have a simple HTTP server 716


Real's HowTo PDF version

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

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("Content-Type", "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.

Handle JSON Object


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-handle-json-object.html

Handle JSON Object 717


Real's HowTo PDF version

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read
and write. It is used primarily to transmit data between a server and web application, as an alternative to
XML.

JSON structures are easy to manipulate from Java. The required libraries are now included in the Java EE 7
specification.

Create a JSON object from a String

In this HowTo, we create a JSON object from a String.

In a MAVEN project, add this dependency

<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.4</version>
</dependency>

or download the jars from https://jsonp.java.net/download.html

import java.io.StringReader;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;

// https://jsonp.java.net/download.html
public class Json1 {
String jsonString = "{" +
" \"firstName\": \"John\", \"lastName\": \"Smith\", \"age\": 25," +
" \"address\" : { " +
" \"streetAddress\": \"21 2nd Street\"," +
" \"city\": \"New York\"," +
" \"state\": \"NY\"," +
" \"postalCode\": \"10021\"" +
" }," +
" \"phoneNumber\": [" +
" { \"type\": \"home\", \"number\": \"212 555-1234\" }," +
" { \"type\": \"fax\", \"number\": \"646 555-4567\" }" +
" ]" +
"}";

public static void main(String args[]) {


Json1 x = new Json1();
x.doit();
}

public void doit() {


JsonReader reader = Json.createReader(new StringReader(jsonString));
JsonObject object = reader.readObject();

Handle JSON Object 718


Real's HowTo PDF version

reader.close();
System.out.println(object.getString("firstName") + " " + object.getString("lastName"))
System.out.println(object.getJsonObject("address").getString("city")) ;
/*
output :
John Smith
New York
*/
}
}

Create a JSON object from a File

To use a file, replace the StringReader by a FileReader.

Create a JSON object from code

Now, we want to create the JSON object from code.

import javax.json.Json;
import javax.json.JsonObject;

public class Json2 {


public static void main(String args[]) {
Json2 x = new Json2();
x.doit();
}

public void doit() {


JsonObject object = Json.createObjectBuilder()
.add("firstName", "John")
.add("lastName", "Smith")
.add("age", 25)
.add("address", Json.createObjectBuilder()
.add("streetAddress", "21 2nd Street")
.add("city", "New York")
.add("state", "NY")
.add("postalCode", "10021"))
.add("phoneNumber", Json.createArrayBuilder()
.add(Json.createObjectBuilder()
.add("type", "home")
.add("number", "212 555-1234"))
.add(Json.createObjectBuilder()
.add("type", "fax")
.add("number", "646 555-4567")))
.build();

System.out.println(object.getString("firstName") + " " + object.getString("lastName"))


System.out.println(object.getJsonObject("address").getString("city")) ;
}
}

Handle JSON Object 719


Real's HowTo PDF version

Create a JSON object from a REST service response

To call the REST service, we will use the HTTPClient module from Apache.

In a MAVEN project, add these dependencies

<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.4</version>
</dependency>

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.5</version>
</dependency>

or download the required jars from :

• https://jsonp.java.net/download.html
• http://hc.apache.org/downloads.cgi

For the demonstration, we call http://jsonplaceholder.typicode.com/ which is Fake Online REST API for
Testing and Prototyping.

The first example calls jsonplaceholder.typicode.com/posts/1 to get the first message. From the response,
we extract the id and the title.

The raw response looks like

{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit ...eveniet architecto"
}

import java.io.InputStreamReader;

import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;

import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

Handle JSON Object 720


Real's HowTo PDF version

public class Json3 {


public static void main(String args[]) throws Exception {
Json3 x = new Json3();
x.doit();
}

public void doit() throws Exception {


JsonReader reader = null;
CloseableHttpClient client = HttpClientBuilder.create().build();
HttpHost target = new HttpHost("jsonplaceholder.typicode.com", 80, "http");
HttpGet request = new HttpGet("/posts/1");
request.addHeader("accept", "application/json");
CloseableHttpResponse response = null;
try {
response = client.execute(target, request);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new Exception("Failed : HTTP error code : "
+ response.getStatusLine().getStatusCode());
}

reader = Json.createReader(new InputStreamReader((response.getEntity().getContent())


JsonObject object = reader.readObject();

// System.out.println("raw : " + object.toString()) ;


System.out.println("id : " + object.getJsonNumber("id")) ;
System.out.println("title : " + object.getString("title")) ;
/*
output
id : 1
title : sunt aut facere repellat provident occaecati excepturi optio reprehende
Done.
*/
}
finally {
if (reader != null) reader.close();
if (client != null) client.close();
if (response != null) response.close();
System.out.println("Done.");
}
}
}

Now we call jsonplaceholder.typicode.com/posts which returns a message list of 100 elements. From the
response, we iterate the returned array to display the id and the title.

The raw response looks like

[
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",

Handle JSON Object 721


Real's HowTo PDF version

"body": "quia et suscipit ...eveniet architecto"


}
...
{
"userId": 10,
"id": 100,
"title": "at nam consequatur ea labore ea harum",
"body": "cupiditate quo est a modi nesciunt ... ratione error aut"
}
]

import java.io.InputStreamReader;

import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonReader;

import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

public class Json4 {


public static void main(String args[]) throws Exception {
Json4 x = new Json4();
x.doit();
}

public void doit() throws Exception {


JsonReader reader = null;
CloseableHttpClient client = HttpClientBuilder.create().build();
HttpHost target = new HttpHost("jsonplaceholder.typicode.com", 80, "http");
HttpGet request = new HttpGet("/posts");
request.addHeader("accept", "application/json");
CloseableHttpResponse response = null;
try {
response = client.execute(target, request);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new Exception("Failed : HTTP error code : "
+ response.getStatusLine().getStatusCode());
}

reader = Json.createReader(new InputStreamReader((response.getEntity().getContent())


JsonArray array = reader.readArray();

for (int j = 0; j < array.size(); j++ ) {


JsonObject jo = array.getJsonObject(j);
System.out.println("id : " + jo.getJsonNumber("id")) ;
System.out.println("title : " + jo.getString("title")) ;
}
/*

Handle JSON Object 722


Real's HowTo PDF version

output
id : 1
title : sunt aut facere repellat provident occaecati excepturi optio reprehende
...
id : 100
title : at nam consequatur ea labore ea harum
Done.
*/
}
finally {
if (reader != null) reader.close();
if (client != null) client.close();
if (response != null) response.close();
System.out.println("Done.");
}
}
}

The same operation using JsonParser and InputStream

import java.io.InputStream;

import javax.json.Json;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;

import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

//https://jsonp.java.net/download.html
//http://hc.apache.org/downloads.cgi

public class Json5 {

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


Json5 x = new Json5();
x.doit();
}

public void doit() throws Exception {


CloseableHttpClient client = HttpClientBuilder.create().build();
HttpHost target = new HttpHost("jsonplaceholder.typicode.com", 80, "http");
HttpGet request = new HttpGet("/posts");
request.addHeader("accept", "application/json");
CloseableHttpResponse response = null;
try {
response = client.execute(target, request);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new Exception("Failed : HTTP error code : "

Handle JSON Object 723


Real's HowTo PDF version

+ response.getStatusLine().getStatusCode());
}

InputStream is = response.getEntity().getContent();
JsonParser parser = Json.createParser(is);
while (parser.hasNext()) {
Event e = parser.next();
if (e == Event.KEY_NAME) {
switch (parser.getString()) {
case "id":
parser.next();
System.out.print(parser.getString());
System.out.print(": ");
break;
case "title":
parser.next();
System.out.println(parser.getString());
System.out.println("---------");
break;
}
}
}
/*
output :
1: sunt aut facere repellat provident occaecati excepturi optio reprehenderit
-------------
2: qui est esse
---------
...
99: temporibus sit alias delectus eligendi possimus magni
---------
100: at nam consequatur ea labore ea harum
---------
Done.
*/
}
finally {
if (client != null) client.close();
if (response != null) response.close();
System.out.println("Done.");
}
}
}

Create a Java object from a JSON object

It's possible to do it by hand by calling the jasonobject.get[type] and the corresponding DTO/POJO set
methods. But it is easier to use a library to handle the finer details. One library which is nice is GSON.

In Maven project, use

<dependency>
<groupId>com.google.code.gson</groupId>

Handle JSON Object 724


Real's HowTo PDF version

<artifactId>gson</artifactId>
<version>2.3.1</version>
</dependency>

or download the jar from here

Again from our REST example at jsonplaceholder.typicode.com/posts/1 , we define a DTO/POJO as :

public class JsonPlaceHolderPosts {


int userid;
int id;
String title;
String body;

public int getUserid() {


return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}

and then from a JSON stream, we create the Java object

import java.io.InputStreamReader;

import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

import com.google.gson.Gson;

Handle JSON Object 725


Real's HowTo PDF version

// https://jsonp.java.net/download.html
// http://hc.apache.org/downloads.cgi
// http://search.maven.org/#artifactdetails|com.google.code.gson|gson|2.3.1|jar

public class Json6 {

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


Json6 x = new Json6();
x.doit();
}

public void doit() throws Exception {


CloseableHttpClient client = HttpClientBuilder.create().build();
HttpHost target = new HttpHost("jsonplaceholder.typicode.com", 80, "http");
HttpGet request = new HttpGet("/posts/1");
request.addHeader("accept", "application/json");
CloseableHttpResponse response = null;
try {
response = client.execute(target, request);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new Exception("Failed : HTTP error code : "
+ response.getStatusLine().getStatusCode());
}

Gson gson = new Gson();


JsonPlaceHolderPosts jphp = gson.fromJson(new InputStreamReader
(response.getEntity().getContent()), JsonPlaceHolderPosts.class);
System.out.println("id : " + jphp.getId()) ;
System.out.println("title : " + jphp.getTitle()) ;
/*
ouput:
id : 1
title : sunt aut facere repellat provident occaecati excepturi optio reprehende
Done.
*/
}
finally {
if (client != null) client.close();
if (response != null) response.close();
System.out.println("Done.");
}
}
}

Create a JSON string from a Java object

Finally, from a Java object, create a JSON string.

import com.google.gson.Gson;

// http://search.maven.org/#artifactdetails|com.google.code.gson|gson|2.3.1|jar

public class Json7 {

Handle JSON Object 726


Real's HowTo PDF version

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


Json7 x = new Json7();
x.doit();
}

public void doit() throws Exception {


JsonPlaceHolderPosts jphp = new JsonPlaceHolderPosts();
jphp.setUserid(1111);
jphp.setId(2222);
jphp.setTitle("foo");
jphp.setBody("bar");

Gson gson = new Gson();


String json = gson.toJson(jphp, JsonPlaceHolderPosts.class);
System.out.println("json : " + json) ;
System.out.println("Done.");
/*
output :
json : {"userid":1111,"id":2222,"title":"foo","body":"bar"}
Done.
*/
}
}

HttpUrlConnection with GZIP encoding


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-HttpUrlConnection-with-GZIP-encoding.html

By default, when you make a request to URL, the response is not compressed.

import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpConnect {


public static void main(String[] args) throws Exception {
URL url = new URL("http://www.rgagnon.com/howto.html");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
// con.setRequestProperty("Accept-Encoding", "gzip");
System.out.println("Length : " + con.getContentLength());
Reader reader = new InputStreamReader(con.getInputStream());
while (true) {
int ch = reader.read();
if (ch==-1) {
break;
}
System.out.print((char)ch);
}

HttpUrlConnection with GZIP encoding 727


Real's HowTo PDF version

}
}

From the response, we see that the length is 21740 bytes.

Length : 21740
<!DOCTYPE HTML>
<HTML>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<LINK REL="SHORTCUT ICON" HREF="http://www.rgagnon.com/favicon.ico">
<META NAME="description"
Content="Real's JAVA JAVASCRIPT WSH and PowerBuilder How-to pages with useful cod
<META NAME="keywords"
Content="java,javascript,wsh,vbscript,how-to,powerbuilder">
...

By setting the Request Header "Accept" to "gzip", we are telling to the server that we want the response to
be compressed if possible with the GZIP compression scheme. If it's not supported by the server then the
response will be sent as plain text.

import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpConnect {


public static void main(String[] args) throws Exception {
URL url = new URL("http://www.rgagnon.com/howto.html");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("Accept-Encoding", "gzip");
System.out.println("Length : " + con.getContentLength());
Reader reader = new InputStreamReader(con.getInputStream());
while (true) {
int ch = reader.read();
if (ch==-1) {
break;
}
System.out.print((char)ch);
}
}
}

Now the response length is 4865 but the content is not readable because we need to uncompress it!

Length : 4865
j¼Eðßôš[è^úðGR¾vø
...

We add a check to determine if the response is compressed or not to use the appropriate InputStream

HttpUrlConnection with GZIP encoding 728


Real's HowTo PDF version

because the web server is by no means obliged to use any compression method - this depends on the
internal settings of the web server.

import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.zip.GZIPInputStream;

public class HttpConnect {


public static void main(String[] args) throws Exception {
URL url = new URL("http://www.rgagnon.com/howto.html");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("Accept-Encoding", "gzip");
System.out.println("Length : " + con.getContentLength());

Reader reader = null;


if ("gzip".equals(con.getContentEncoding())) {
reader = new InputStreamReader(new GZIPInputStream(con.getInputStream()));
}
else {
reader = new InputStreamReader(con.getInputStream());
}

while (true) {
int ch = reader.read();
if (ch==-1) {
break;
}
System.out.print((char)ch);
}
}
}

And the result is

Length : 4865
<!DOCTYPE HTML>
<HTML>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<LINK REL="SHORTCUT ICON" HREF="http://www.rgagnon.com/favicon.ico">
<META NAME="description"
Content="Real's JAVA JAVASCRIPT WSH and PowerBuilder How-to pages with useful cod
<META NAME="keywords"
Content="java,javascript,wsh,vbscript,how-to,powerbuilder">
...

HttpUrlConnection with GZIP encoding 729


Real's HowTo PDF version

Connect through a Proxy


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0085.html

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

Connect through a Proxy 730


Real's HowTo PDF version

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

Proxy and Username/Password

You might need to identify yourself to the proxy server.

One way is to use the HTTP property "Proxy-Authorization" with a username:password base64 encoded.

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("Proxy-Authorization", "Basic " + encoded);
uc.connect();

NOTE: For a base64 function, see this How-to.

The following example dumps the content of a URL but before we identify ourself to the proxy.
import java.net.*;
import java.io.*;

public class URLUtils {


public static void main(String s[]) {
URLUtils.dump("http://www.yahoo.com");

Connect through a Proxy 731


Real's HowTo PDF version

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
("Proxy-Authorization", "Basic " + encodedUserPwd);
// PROXY ----------

di = new DataInputStream(con.getInputStream());
while(-1 != di.read(b,0,1)) {
System.out.print(new String(b));
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}

With JDK1.2, the java.net.Authenticator can be used to send the credentials when needed.

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

Connect through a Proxy 732


Real's HowTo PDF version

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

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

Have timeout on socket connection


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0086.html

[JDK11]

ServerSocket server = new ServerSocket(port);


// timeout after 60 seconds
server.setSoTimeout(60000);
try {
Socket socket=server.accept();
}
catch ( java.io.InterruptedIOException e ) {
System.err.println( "Timed Out (60 sec)!" );
}

This is true for READ operation too. Since READ operation blocks as long necessary it may be wise to use
the setSoTimeout() method. Note that when the TIMEOUT expires, an InterruptException is thrown.
However, the socket is still connected even though the Exception was raised.

Connect through a Proxy 733


Real's HowTo PDF version

Ping a server
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0093.html

It's not possible to really "ping" a machine to check if it's alive or not (it's a long story, but to keep it short I
will just say that the Socket class is not low-level enough for that operation). But we can emulate a ping by
talking the "echo port". On a server, the echo port is always port 7. We write a string to that port and the
server will echo the string.

import java.io.*;
import java.net.*;

public class PseudoPing {


public static void main(String args[]) {
try {
Socket t = new Socket(args[0], 7);
DataInputStream dis = new DataInputStream(t.getInputStream());
PrintStream ps = new PrintStream(t.getOutputStream());
ps.println("Hello");
String str = dis.readLine();
if (str.equals("Hello"))
System.out.println("Alive!") ;
else
System.out.println("Dead or echo port not responding");
t.close();
}
catch (IOException e) {
e.printStackTrace();}
}
}
}

NOTE: To make this a more "complete PING", you may want to check this How-to to display the response time.

Since JDK1.5, java.net.InetAddress.isReachable(int) can be used to check if a server is reachable or not.

import java.io.*;
import java.net.*;

public class ReachableTest {


public static void main(String args[]) {
try {
InetAddress address = InetAddress.getByName("web.mit.edu");
System.out.println("Name: " + address.getHostName());
System.out.println("Addr: " + address.getHostAddress());
System.out.println("Reach: " + address.isReachable(3000));
}
catch (UnknownHostException e) {
System.err.println("Unable to lookup web.mit.edu");

Ping a server 734


Real's HowTo PDF version

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

Get the Date from server


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0094.html

This can be done by opening a socket to the port "daytime" (port 13) (on Unix or NT machine).

import java.net.*;
import java.io.*;

public class GetTime {


public static void main(String args[]) {
if (args.length != 1) {
System.out.println("Usage: GetTime HOST");
return;
}
try {
Socket s = new Socket(args[0],13);
InputStream is = s.getInputStream();
while (true) {
byte b[] = new byte[100];
int i=is.read(b);
if (i==-1) return;
System.out.print(new String(b,0,i));
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}

Use Socket's setSoLinger()


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0293.html

Get the Date from server 735


Real's HowTo PDF version

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

Use Socket's setTcpNoDelay()


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0294.html

java.net.Socket.setTcpNoDelay() is used to enable/disable TCP_NODELAY which disable/enable Nagle's


algorithm.

Nagle's algorithm try to conserve bandwidth by minimizing the number of segments that are sent. When
applications wish to decrease network latency and increase performance, they can disable Nagle's algorithm
(that is enable TCP_NODELAY). Data will be sent earlier, at the cost of an increase in bandwidth
consumption. The Nagle's algorithm is described in RFC 896.

You get the current "TCP_NODELAY" setting with java.net.Socket.getTcpNoDelay()

Find who is connecting to a ServerSocket


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0295.html

Socket aSock = myServerSocket.accept();

System.out.println
("Connection from : "
+ aSock.getInetAddress().getHostAddress()
+ ':' + aSock.getPort());

Use Socket's setSoLinger() 736


Real's HowTo PDF version

Transfer a file via Socket


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0542.html

A client module connects to a server then a file is sent to the client.

This example is very simple with no authentication and hard-coded filename!

First the server module.

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import 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;
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();

Transfer a file via Socket 737


Real's HowTo PDF version

if (os != null) os.close();


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

The client module

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import 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/source-downloaded.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 {
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.length-current));
if(bytesRead >= 0) current += bytesRead;

Transfer a file via Socket 738


Real's HowTo PDF version

} 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 built-in JDK HTTP server, see this HowTo

Check if a document exists in a Sharepoint library


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-check-document-exists-sharepoint-library.html

To check if a document is present in a Sharepoint library, we are using the REST API provided by
Microsoft. All we need is the Apache HttpComponents library to make the call.

If you are using Maven, here is the POM

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.5</version>
</dependency>

To check if a document exists or not, we try to get its Etag (Entity-tag).

import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.BasicCredentialsProvider;

Check if a document exists in a Sharepoint library 739


Real's HowTo PDF version

import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class HttpDocumentExistsWithHttpClient {

/**
* check if a document exists in a sharepoint library
*/
public static void main(String[] args) throws Exception{
CloseableHttpClient httpclient = HttpClients.custom()
.setRetryHandler(new DefaultHttpRequestRetryHandler(0,false))
.build();

String user = "myusername";


String pwd = "mypassword";
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
new NTCredentials(user, pwd, "", ""));

// You may get 401 if you go through a load-balancer.


// To fix this, go directly to one of the sharepoint web server or
// change the config. See this article :
// http://blog.crsw.com/2008/10/14/unauthorized-401-1-exception-calling-web-services-in-
HttpHost target = new HttpHost("web01.mysharepoint.local", 80, "http");
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);

// The authentication is NTLM.


// To trigger it, we send a minimal http request
HttpHead request1 = new HttpHead("/");
CloseableHttpResponse response1 = null;
try {
response1 = httpclient.execute(target, request1, context);
EntityUtils.consume(response1.getEntity());
System.out.println("1 : " + response1.getStatusLine().getStatusCode());
}
finally {
if (response1 != null ) response1.close();
}

// The real request, reuse authentication


String file = "/30500C/PubDoc/TEST/jira.log"; // source
HttpGet request2 = new HttpGet("/_api/web/GetFileByServerRelativeUrl('" + file + "')/Eta
CloseableHttpResponse response2 = null;
try {
response2 = httpclient.execute(target, request2, context);
EntityUtils.consume(response2.getEntity());
int rc = response2.getStatusLine().getStatusCode();
String reason = response2.getStatusLine().getReasonPhrase();
if (rc != HttpStatus.SC_OK) {

Check if a document exists in a Sharepoint library 740


Real's HowTo PDF version

System.out.println(file + " is missing. Reason : "


+ reason + " rc : " + rc + "(500 is the equivalent of NOT FOUND)");
}
else {
System.out.println(file + " exists.");
}
}
finally {
if (response2 != null) response2.close();
}
return;
}
}

See also :

• Delete a document in a Sharepoint library


• Put a document into a Shrepoint library
• Get a document from a Sharepoint library

Delete a document in a Sharepoint library


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-delete-document-sharepoint-library.html

To delete a document in a Sharepoint library, we are using the REST API provided by Microsoft.
All we need is the Apache HttpComponents library to make the call.

If you are using Maven, here is the POM

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.5</version>
</dependency>

import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

Delete a document in a Sharepoint library 741


Real's HowTo PDF version

public class HttpDeleteWithHttpClient {

/**
* delete a file in a sharepoint library
*/
public static void main(String[] args) throws Exception{
CloseableHttpClient httpclient = HttpClients.custom()
.setRetryHandler(new DefaultHttpRequestRetryHandler(0,false))
.build();

String user = "myusername";


String pwd = "mypassword";
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
new NTCredentials(user, pwd, "", ""));

// You may get 401 if you go through a load-balancer.


// To fix this, go directly to one the sharepoint web server or
// change the config. See this article :
// http://blog.crsw.com/2008/10/14/unauthorized-401-1-exception-calling-web-servic
HttpHost target = new HttpHost("web.mysharepoint.local", 80, "http");
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);

// The authentication is NTLM.


// To trigger it, we send a minimal http request
HttpHead request1 = new HttpHead("/");
CloseableHttpResponse response1 = null;
try {
response1 = httpclient.execute(target, request1, context);
EntityUtils.consume(response1.getEntity());
System.out.println("1 : " + response1.getStatusLine().getStatusCode());
}
finally {
if (response1 != null ) response1.close();
}

// The real request, reuse authentication


HttpDelete request2 = new HttpDelete("/30500C/PubDoc/TEST/jira.log"); // target
CloseableHttpResponse resp = httpclient.execute(target,request2, context);
System.out.println("2 : " + resp.getStatusLine().getStatusCode());
resp.close();

//
// 204 No Content
// The server successfully processed the request, but is not returning any con
// Usually used as a response to a successful delete request.
// other
// we have a problem
}
}

Delete a document in a Sharepoint library 742


Real's HowTo PDF version

See also :

♦ Check if a document exists in a Sharepoint library


♦ Get a document from a Sharepoint library
♦ Put a document into a Sharepoint library
Get a document from a Sharepoint library
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-get-document-sharepoint-library.html

To retrieve or download a document from a Sharepoint library, we are using the REST API
provided by Microsoft. All we need is the Apache HttpComponents.

If you are using Maven, here is the POM

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.5</version>
</dependency>

import java.io.File;

import org.apache.commons.io.FileUtils;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class HttpGetWithHttpClient {

/**
* download a file from a sharepoint library
*/
public static void main(String[] args) throws Exception{
CloseableHttpClient httpclient = HttpClients.custom()

Get a document from a Sharepoint library 743


Real's HowTo PDF version

.setRetryHandler(new DefaultHttpRequestRetryHandler(0,false))
.build();

String user = "myusername";


String pwd = "mypassword";
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
new NTCredentials(user, pwd, "", ""));

// You may get 401 if you go through a load-balancer.


// To fix this, go directly to one of the sharepoint web server or
// change the config. See this article :
// http://blog.crsw.com/2008/10/14/unauthorized-401-1-exception-calling-web-servic
HttpHost target = new HttpHost("web.mysharepoint.local", 80, "http");
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);

// The authentication is NTLM.


// To trigger it, we send a minimal http request
HttpHead request1 = new HttpHead("/");
CloseableHttpResponse response1 = null;
try {
response1 = httpclient.execute(target, request1, context);
EntityUtils.consume(response1.getEntity());
System.out.println("1 : " + response1.getStatusLine().getStatusCode());
}
finally {
if (response1 != null ) response1.close();
}

// The real request, reuse authentication


String file = "/30500C/PubDoc/TEST/jira.log"; // source
String targetFolder = "C:/TEMP";
HttpGet request2 = new HttpGet("/_api/web/GetFileByServerRelativeUrl('" + file + "
CloseableHttpResponse response2 = null;
try {
response2 = httpclient.execute(target, request2, context);
HttpEntity entity = response2.getEntity();
int rc = response2.getStatusLine().getStatusCode();
String reason = response2.getStatusLine().getReasonPhrase();
if (rc == HttpStatus.SC_OK) {
System.out.println("Writing "+ file + " to " + targetFolder);
File f = new File(file);
File ff= new File(targetFolder, f.getName()); // target
// writing the byte array into a file using Apache Commons IO
FileUtils.writeByteArrayToFile(ff, EntityUtils.toByteArray(entity));
}
else {
throw new Exception("Problem while receiving " + file + " reason : "
+ reason + " httpcode : " + rc);
}
}
finally {

Get a document from a Sharepoint library 744


Real's HowTo PDF version

if (response2 != null) response2.close();


}
return;
}
}

See also :

♦ Check if a document exists in a Sharepoint library


♦ Delete a document in a Sharepoint library
♦ Put a document into a Sharepoint library
Put or store a document in a Sharepoint library
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-put-document-sharepoint-library.html

To store or upload a document into a Sharepoint library, we are using the REST API provided by
Microsoft. All we need is the Apache HttpComponents library.

If you are using Maven, here is the POM

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.5</version>
</dependency>

import java.io.File;

import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class HttpPutWithHttpClient {

/**

Put or store a document in a Sharepoint library 745


Real's HowTo PDF version

* upload a file to a sharepoint library


*/
public static void main(String[] args) throws Exception{
CloseableHttpClient httpclient = HttpClients.custom()
.setRetryHandler(new DefaultHttpRequestRetryHandler(0,false))
.build();

String user = "myusername";


String pwd = "mypassword";
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
new NTCredentials(user, pwd, "", ""));

// You may get 401 if you go through a load-balancer.


// To fix this, go directly to one the sharepoint web server or
// change the config. See this article :
// http://blog.crsw.com/2008/10/14/unauthorized-401-1-exception-calling-web-servic
HttpHost target = new HttpHost("web.mysharepoint.local", 80, "http");
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);

// The authentication is NTLM.


// To trigger it, we send a minimal http request
HttpHead request1 = new HttpHead("/");
CloseableHttpResponse response1 = null;
try {
response1 = httpclient.execute(target, request1, context);
EntityUtils.consume(response1.getEntity());
System.out.println("1 : " + response1.getStatusLine().getStatusCode());
}
finally {
if (response1 != null ) response1.close();
}

// The real request, reuse authentication


String file = "/30500C/PubDoc/TEST/jira.log";
HttpPut request2 = new HttpPut("/30500C/PubDoc/TEST/jira.log"); // target
request2.setEntity(new FileEntity(new File("c:/temp/jira.log")));// source
CloseableHttpResponse response2 = null;
try {
response2 = httpclient.execute(target, request2, context);
EntityUtils.consume(response2.getEntity());
int rc = response2.getStatusLine().getStatusCode();
String reason = response2.getStatusLine().getReasonPhrase();
// The possible outcomes :
// 201 Created
// The request has been fulfilled and resulted in a new resource being cr
// 200 OK
// Standard response for successful HTTP requests.
// others
// we have a problem
if (rc == HttpStatus.SC_CREATED) {
System.out.println(file + " is copied (new file created)");

Put or store a document in a Sharepoint library 746


Real's HowTo PDF version

}
else if (rc == HttpStatus.SC_OK) {
System.out.println(file + " is copied (original overwritten)");
}
else {
throw new Exception("Problem while copying " + file
+ " reason " + reason + " httpcode : " + rc);
}
}
finally {
if (response2 != null) response2.close();
}
return;
}
}

See also :

♦ Check if a document exists in a Shrepoint library


♦ Delete a document in a Sharepoint library
♦ Get a document from a Sharepoint library
Handle MS Exchange public folders
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-handle-exchange-public-folders.html

You can access the public folders from Microsoft Exchange by calling the Exchange Web Services
(EWS). An Open Source library is available to allow Java program to easily call thoses services,
ews-java-api. You can get a ready to use jar at the Sonatype OSS repository. Be sure to get all the
dependencies! With Maven, use this POM :

<dependency>
<groupId>com.microsoft.ews-java-api</groupId>
<artifactId>ews-java-api</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>

Handle MS Exchange public folders 747


Real's HowTo PDF version

to connect

ExchangeService service = new ExchangeService();


ExchangeCredentials credentials = new WebCredentials("[email protected]", "mypwd");
service.setCredentials(credentials);
service.setUrl(new URI("https://myexchangemailserver.com/ews/Exchange.asmx"));

to retrieve the first 5 public folders from the root

FolderView view = new FolderView(5);


FindFoldersResults findResults = service.findFolders(WellKnownFolderName.PublicFolder
for (Folder item : findResults.getFolders()) {
System.out.println(item.getDisplayName());
}

to navigate, you position yourself level by level. You can save each item of a folder as EML file.
EML is the format used by Exchange and can be opened by Outlook or any mail client and be
parsed by JavaMail .

For example, we want to go in the folder \level1\level2, then save the first 5 items as EML files.

// search for a specific folder and then list the first 5 item
FolderView view = new FolderView(10);
SearchFilter filter = new SearchFilter.ContainsSubstring(FolderSchema.DisplayName, "l
FindFoldersResults findResults = service.findFolders(WellKnownFolderName.PublicFolder

// for (Folder item : findResults.getFolders()) {


// System.out.println("* " + item.getDisplayName());
// }

SearchFilter filter2 = new SearchFilter.ContainsSubstring(FolderSchema.DisplayName, "


FindFoldersResults findResults2 = findResults.getFolders().get(0).findFolders(filter2

ItemView view2 = new ItemView(5);

FindItemsResults<Item> findResults3 = findResults2.getFolders().get(0).findItems(view

// save .eml
for (Item item : findResults3.getItems()) {
System.out.println("!! " + item.getSubject());
String subject = item.getSubject();
item.load(new PropertySet(ItemSchema.MimeContent));

MimeContent mc = item.getMimeContent();
// it may be a good idea to sanitize a little bit the filename to remove illega
// see this HowTo
FileOutputStream fs = new FileOutputStream("c:/temp/" + subject + ".eml");

byte b[] = mc.getContent();


fs.write(b, 0, b.length);
fs.close();
}

Handle MS Exchange public folders 748


Real's HowTo PDF version

to delete

for (Item item : findResults3.getItems()) {


System.out.println("** " + item.getSubject() + " " + item.getDateTimeSent());
item.delete(DeleteMode.HardDelete);
}

when done, don't forget to close your connection!

service.close();
System.out.println("Done.");

In this HowTo, EWS was used to access the public folders but you can use it to send/receive
regular mail or create appointment/task. See
https://github.com/OfficeDev/ews-java-api/blob/master/readme.md for more details.

Written and compiled Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Handle MS Exchange public folders 749


Open Source
java-os

Call Windows API


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0497.html

NativeCall
NativeCall is a Java toolkit that lets you call operating system methods from whithin Java without JNI code.

// copying a file to a new one using the Windows API


import com.eaio.nativecall.*;

NativeCall.init();
IntCall ic = new IntCall("CopyFileA");
ic.executeCall(new Object[] { "test.txt", "test_copy.txt", Boolean.FALSE });
ic.destroy();

See http://johannburkard.de/software/nativecall/

Call COM object


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0498.html

com4j

A Java library that allows Java applications to seemlessly interoperate with Microsoft Component Object
Model.

First generate Java type definitions from a COM type library. Here we are doing for the type library for the
Windows Scripting Host.

> java -jar tlbimp.jar -o wsh -p test.wsh %WINDIR%\system32\wshom.ocx

Then we are able to call WSH objects/methods.

public class Main {


public static void main(String[] args) {
IFileSystem3 fs = ClassFactory.createFileSystemObject();

Open Source 750


Real's HowTo PDF version

for( String file : args )


System.out.println(fs.getFileVersion(file));
}
}

https://com4j.dev.java.net/

j-interop

Implementation of DCOM wire protocol (MSRPC) to enable development of Pure Bi-Directional, Non-Native
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/j-interop

j-xchange

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

See also this HowTo for an alternative package to access a COM package from Java.

Create entity-relation diagram


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0584.html

Linguine Maps is an open-source Java library that conducts programmatic visualization of various text files,
generating from them easy-to-understand entity-relation diagrams.

http://www.softwaresecretweapons.com/jspwiki/linguinemaps

One interesting use is the Linguine Maps for Apache Ant. This utility produces easy to read diagrams from
Ant build files. The diagram shows all the task dependencies and colors default, normal, and optional task in
different colors. Tis a great way to document your Ant build file.

Call COM object 751


Real's HowTo PDF version

Java Remote desktop tool


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0583.html

Java Remote Desktop Protocol (RDP) Client is an Open Source Java RDP client for Windows Terminal
Server.

It runs on Java 1.1 and up, and works on Linux, Windows, Mac and other Java enabled systems.
http://www.elusiva.com/opensource/

Simply pass the machine name to connect to on the command line.

javaw -jar JavaRDP13-1.1.jar some.machine.local

For more option, from a command shell

javaw -jar JavaRDP14-1.1.jar

There is a port for OpenVMS called JavaRDP for OpenVMS at http://vmsfree.free.fr/freen/index.php?id=38

Create entity-relation diagram 752


Real's HowTo PDF version

Create entity-relation diagram


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0584.html

Linguine Maps is an open-source Java library that conducts programmatic visualization of various text files,
generating from them easy-to-understand entity-relation diagrams.

http://www.softwaresecretweapons.com/jspwiki/linguinemaps

One interesting use is the Linguine Maps for Apache Ant. This utility produces easy to read diagrams from
Ant build files. The diagram shows all the task dependencies and colors default, normal, and optional task in
different colors. Tis a great way to document your Ant build file.

Launch a java program as a Windows EXE file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0588.html

Create entity-relation diagram 753


Real's HowTo PDF version

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.
• Built-in icon replacer for custom icon.
• Windows NT Service wrapper.
• Windows EventLog API
• 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

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 Swing-based 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.

Launch4J

http://launch4j.sourceforge.net/

Launch4j is a cross-platform 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...

Launch a java program as a Windows EXE file 754


Real's HowTo PDF version

• Runtime JVM options from an .l4j.ini file.


• Custom version information shown by Windows Explorer.
• GUI, command line interface, Ant task and Maven plugin.

Tools to handle CSV files


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0591.html

com.Ostermiller.util CSV Utils

CSVPrinter/CSVParser/ExcelCSVPrinter/ExcelCSVParser
http://ostermiller.org/utils/CSV.html

opencsv

A simple csv parser library for Java


http://opencsv.sourceforge.net/

ServingXML

Framework for flat/XML data transformations. Supported transformations : flat-XML, XML-flat,


flat-flat, and XML-XML
http://servingxml.sourceforge.net/

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/

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

CSVFile

A simple set of Java classes used to handle CSV


http://sourceforge.net/projects/csvfile

Tools to handle CSV files 755


Real's HowTo PDF version

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/

CSVJDBC

CsvJdbc is a simple read-only JDBC driver that uses Comma Separated Value (CSV) files as database
tables.
http://csvjdbc.sourceforge.net/

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 multi-line formats and files containing lines have
different known formats ("mixed format" files).
http://jffp.sourceforge.net/

XSLT

XSLT is built-in in the JDK, you need to create your own transformation in a XSL file. Transform
XML into CSV using XSLT

Tools to handle Excel files


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0516.html

There are many solutions to read or write Excel spreadsheets from Java. This HowTo is only about
OpenSource (and free) solutions.

JDBC-ODBC Excel driver

For Java 8 you cannot use the JDBC-ODBC Bridge because it has been removed.
This solution lets you access your Excel worksheet with SQL SELECT statement. The required
ODBC driver is included in a regular Windows installation and the JDBC-ODBC bridge is used to
access the Excel DSN.

See this HowTo for an example.

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

Tools to handle CSV files 756


Real's HowTo PDF version

Excel spreadsheets. One nice thing about JExcelApi is that it has no dependencies on any third party
libraries.

Example : output an Excel file from a Servlet

import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

public class Sample extends HttpServlet {


public void doGet
(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
OutputStream out = null;
try {
response.setContentType("application/vnd.ms-excel");
response.setHeader
("Content-Disposition", "attachment; filename=sampleName.xls");
WritableWorkbook w =
Workbook.createWorkbook(response.getOutputStream());
WritableSheet s = w.createSheet("Demo", 0);
s.addCell(new Label(0, 0, "Hello World"));
w.write();
w.close();
}
catch (Exception e){
throw new ServletException("Exception in Excel Sample Servlet", e);
}
finally{
if (out != null)
out.close();
}
}
}

See http://jexcelapi.sourceforge.net/

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.

Tools to handle Excel files 757


Real's HowTo PDF version

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/

JXLS

jXLS is a project that allows creation of extremely complex Excel reports just in several lines of code.
It is based on Jakarta POI.

With jXLS, all you need is to create XLS template file with all required formatting, formulas etc
using specific notation to indicate placement of data and then write a couple lines of code to invoke
jXLS engine passing XLS template and the exported data as parameters.

Example :
The XLS Template

Employees
Name Age Payment Bonus
${employee.name} ${employee.age} ${employee.payment} ${employee.bonus}
$[SUM(@employee.payment@)]

with the code

Collection staff = new HashSet();


staff.add(new Employee("Derek", 35, 3000, 0.30));
staff.add(new Employee("Elsa", 28, 1500, 0.15));
Map beans = new HashMap();
beans.put("employee", staff);
XLSTransformer transformer = new XLSTransformer();
transformer.transformXLS(templateFileName, beans, destFileName);

Tools to handle Excel files 758


Real's HowTo PDF version

gives the result

Employees
Name Age Payment Bonus
Derek 35 3000 30,00%
Else 28 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/

xlSQL

xlSQL is a JDBC Driver for Excel and CSV data sources. Documents can be read and written with
SQL as if they were tables in a database.

You can export XLS to XML or SQL INSERT statements. xlSQL includes its own "zero-admin"
mySQL database. The documentation is minimal at this time.

See http://xlsql.sourceforge.net/

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 :

Tools to handle Excel files 759


Real's HowTo PDF version

import jp.ne.so_net.ga2.no_ji.jcom.excel8.*;
import jp.ne.so_net.ga2.no_ji.jcom.*;
import java.io.File;
import java.util.Date;

class TestExcel {
public static void main(String[] args) throws Exception {
ReleaseManager rm = new ReleaseManager();
try {
System.out.println("EXCEL startup...");
// if already started, open new window
ExcelApplication excel = new ExcelApplication(rm);
excel.Visible(true);
// display any information
System.out.println("Version="+excel.Version());
System.out.println("UserName="+excel.UserName());
System.out.println("Caption="+excel.Caption());
System.out.println("Value="+excel.Value());

ExcelWorkbooks xlBooks = excel.Workbooks();


ExcelWorkbook xlBook = xlBooks.Add(); // create new book

// enumurate all files


System.out.println
("set infomation of files in current directory to cell ...");
ExcelWorksheets xlSheets = xlBook.Worksheets();
ExcelWorksheet xlSheet = xlSheets.Item(1);
ExcelRange xlRange = xlSheet.Cells();

xlRange.Item(1,1).Value("filename" );
xlRange.Item(2,1).Value("size" );
xlRange.Item(3,1).Value("last modified time");
xlRange.Item(4,1).Value("is directory");
xlRange.Item(5,1).Value("is file");
xlRange.Item(6,1).Value("can read");
xlRange.Item(7,1).Value("can write");

File path = new File("./");


String[] filenames = path.list();
for(int i=0; i<filenames.length; i++) {
File file = new File(filenames[i]);
System.out.println(file);
xlRange.Item(1,i+2).Value( file.getName() );
xlRange.Item(2,i+2).Value( (int)file.length() );
xlRange.Item(3,i+2).Value( new Date(file.lastModified()) );
xlRange.Item(4,i+2).Value( file.isDirectory()?"Yes":"No" );
xlRange.Item(5,i+2).Value( file.isFile()?"Yes":"No" );
xlRange.Item(6,i+2).Value( file.canRead()?"Yes":"No" );
xlRange.Item(7,i+2).Value( file.canWrite()?"Yes":"No" );
}
String expression = "=Sum(B2:B"+(filenames.length+1)+")";
System.out.println
("embed equation, calculate sum of filesize: "+expression);
xlRange.Item(1,filenames.length+2).Value("sum");

Tools to handle Excel files 760


Real's HowTo PDF version

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.

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

Tools to handle Excel files 761


Real's HowTo PDF version

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

Tools to handle Excel files 762


Real's HowTo PDF version

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.

Browse a Queue (JMS/MQ)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0472.html

Here 2 nice utilities to browse (and even create) messages. Both are free to use and one is open
source.

WMQTool is more WebSphere MQ oriented.

Hermes is a Swing application that allows you to interact with JMS.

Convert a .class to .java file (decompiler)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0330.html

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

Browse a Queue (JMS/MQ) 763


Real's HowTo PDF version

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.

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 out-dated, the new class format introduced with JDK1.5 is not well supported.

JadClipse

JadClipse is a plug-in 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 plug-in, 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

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 JD-GUI, a standalone graphical utility that displays Java source codes of .class files,
and JD-Eclipse, a plug-in for the Eclipse platform.

http://java.decompiler.free.fr/

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://jar-plug.sourceforge.net/

Convert a .class to .java file (decompiler) 764


Real's HowTo PDF version

Deploy an application as only 1 jar


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0609.html

One-Jar

Any non-trivial 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.

One-Jar is special classloader able to do this. The One-JAR 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 One-Jar application.

http://one-jar.sourceforge.net/

Fat Jar

The Fat Jar Eclipse Plug-In is a Deployment-Tool which deploys an Eclipse java-project into one
executable jar.

http://fjep.sourceforge.net/

Read an Outlook MSG file


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

Deploy an application as only 1 jar 765


Real's HowTo PDF version

which is Microsoft specific.

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 java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import 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 poi-scratchpad-3.6 and poi-3.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 {

Read an Outlook MSG file 766


Real's HowTo PDF version

try {
if(fileIn != null) {
fileIn.close();
}
}
finally {
if(fileOut != null) {
fileOut.close();
}
}
}
}
}
else {
System.out.println("No attachment");
}
}
}

POI 3.7

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.Map;

import org.apache.poi.hdgf.chunks.Chunk;
import org.apache.poi.hsmf.MAPIMessage;
import org.apache.poi.hsmf.datatypes.AttachmentChunks;
import org.apache.poi.hsmf.datatypes.Chunks;
import org.apache.poi.hsmf.exceptions.ChunkNotFoundException;

// You need poi-scratchpad-3.7 and poi-3.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) {

Read an Outlook MSG file 767


Real's HowTo PDF version

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

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 fromEmail = msg.getFromEmail();


String fromName = msg.getFromName();
String subject = msg.getSubject();
String body = msg.getBodyText();

System.out.println("From :" + fromName + " <" + fromEmail + ">");


System.out.println("Subject :" + subject);
System.out.println("");
System.out.println(body);
System.out.println("");

Read an Outlook MSG file 768


Real's HowTo PDF version

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

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

File/directory polling to detect change


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0617.html

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.

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

Read an Outlook MSG file 769


Real's HowTo PDF version

Java Native Access (JNA)

https://github.com/twall/jna#readme

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

Call native methods in a DLL from Java (NativeCall)

http://johannburkard.de/blog/programming/java/Call-native-methods-in-a-DLL-from-Java-without-JNI.html

In this blog entry, the package NativeCall is used to call the Windows API to get notification about
modification in given folder.

Java 7

Java 7 provides a mechanism to get notification on file change without polling (WatchService).

See this HowTo

The simple (and naive!) approach

Detect file modification

Using Threads and file lookup at regular interval.

Jansi/Jcurses - Clear the console and control attributes


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0047.html

There is no built-in way to really control character-based 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

File/directory polling to detect change 770


Real's HowTo PDF version

ANSI escape sequences at all.

Fortunately many Open Source solutions are coming to the rescue and Jansi and JCurses are two of
them.

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 String ANSI_CLS = "\u001b[2J";
public static final String ANSI_HOME = "\u001b[H";
public static final String ANSI_BOLD = "\u001b[1m";
public static final String 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.

Jansi/Jcurses - Clear the console and control attributes 771


Real's HowTo PDF version

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 64-bit OS you need to use JCurses with a
32-bit JVM).

This example will display a character-based window with a label, a textfield and a button (don't click
with you mouse, use the keyboard!).

import jcurses.system.*;
import jcurses.widgets.*;
import jcurses.util.*;
import 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);


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

Jansi/Jcurses - Clear the console and control attributes 772


Real's HowTo PDF version

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

Disable Checkstyle from code


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-disable-checkstyle-from-code.html

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>

Disable Checkstyle from code 773


Real's HowTo PDF version

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

Create or process PDF files


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0523.html

A nice OpenSource is http://www.lowagie.com/iText/ [ITEXT] . iText can deal with RTF and HTML
file too.

Nicely documented with many examples.


• Create a PDF
import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.*;
import com.lowagie.text.pdf.PdfWriter;

public class HelloWorld {


public static void main(String[] args) {
System.out.println("Hello World");
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;

Create or process PDF files 774


Real's HowTo PDF version

import com.lowagie.text.Element;
import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;

public class AddWatermarkPageNumbers {


public static void main(String[] args) {
System.out.println("Add watermarks and pagenumbers");
try {
PdfReader reader = new PdfReader("ChapterSection.pdf");
int n = reader.getNumberOfPages();
// create a stamper that will copy the document to a new file
PdfStamper stamp = new PdfStamper(reader,
new FileOutputStream("watermark_pagenumbers.pdf"));
// adding some metadata
HashMap moreInfo = new HashMap();
moreInfo.put("Author", "Bruno Lowagie");
stamp.setMoreInfo(moreInfo);
// adding content to each page
int i = 0;
PdfContentByte under;
PdfContentByte over;
Image img = Image.getInstance("watermark.jpg");
BaseFont bf =
BaseFont.createFont
(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
img.setAbsolutePosition(200, 400);
while (i < n) {
i++;
// watermark under the existing page
under = stamp.getUnderContent(i);
under.addImage(img);
// text over the existing page
over = stamp.getOverContent(i);
over.beginText();
over.setFontAndSize(bf, 18);
over.setTextMatrix(30, 30);
over.showText("page " + i);
over.setFontAndSize(bf, 32);
over.showTextAligned
(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);

Create or process PDF files 775


Real's HowTo PDF version

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

iText - Create a PDF


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0618.html

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. itext-2.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");

iText - Create a PDF 776


Real's HowTo PDF version

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 page-size 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

Split a PDF file (using iText)


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

Split a PDF file (using iText) 777


Real's HowTo PDF version

/*
* java SplitPDFFile file.pdf
*
* gives file-001.pdf ... file-nnn.pdf
*
* itext-2.1.5.jar
*/

import java.io.FileOutputStream;

import com.lowagie.text.Document;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfImportedPage;
import 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\tx-001.pdf
Writing d:\temp\x\tx-002.pdf
Writing d:\temp\x\tx-003.pdf

Split a PDF file (using iText) 778


Real's HowTo PDF version

*/

}
}

Concatenate PDF files (using iText)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0646.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 com.lowagie.text.Document;
import com.lowagie.text.pdf.PRAcroForm;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfReader;
import 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);
}

Concatenate PDF files (using iText) 779


Real's HowTo PDF version

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.

Convert TIF to PDF


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0645.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 letter-page dimension.

import java.io.FileOutputStream;

import com.lowagie.text.Document;

Convert TIF to PDF 780


Real's HowTo PDF version

import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfWriter;
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;
}
}

Convert TIF to PDF 781


Real's HowTo PDF version

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

Convert HTML to PDF using iText


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-html-to-pdf-using-itext.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 com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.html.simpleparser.HTMLWorker; // deprecated
import com.itextpdf.text.pdf.PdfWriter;

public class HtmlToPDF1 {


// itextpdf-5.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);

Convert HTML to PDF using iText 782


Real's HowTo PDF version

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 [email protected]." +
"<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 com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;
public class HtmlToPDF2 {

// itextpdf-5.4.1.jar http://sourceforge.net/projects/itext/files/iText/
// xmlworker-5.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();

Convert HTML to PDF using iText 783


Real's HowTo PDF version

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 [email protected].</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='background-color: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();
}
}

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

Convert HTML to PDF using YAHP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-convert-html-to-pdf-using-yahp.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 java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

Convert HTML to PDF using YAHP 784


Real's HowTo PDF version

// 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,
"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 java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import 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";

Convert HTML to PDF using YAHP 785


Real's HowTo PDF version

String input = "file_1659686.htm"; // need to be charset utf-8


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.

Convert PNG/JPG/GIF to PDF using iText


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-image-to-pdf-using-itext.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 {

Convert PNG/JPG/GIF to PDF using iText 786


Real's HowTo PDF version

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

Print a PDF
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-print-a-pdf.html

[Windows only]
You can launch the Acrobat Reader to print a PDF to the default printer.

More infos the "unsupported" command-line 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";

Print a PDF 787


Real's HowTo PDF version

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

Extract text from a PDF using Apache Tika


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-extract-text-from-a-pdf.html

You can do it with Apache Tika

import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.tika.parser.pdf.PDFParser;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.sax.BodyContentHandler;
import org.xml.sax.ContentHandler;

public class ParsePDFWithTika {


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

InputStream is = null;
try {
is = new FileInputStream("C:/Temp/realhowto-vbs-20121221.pdf");
ContentHandler contenthandler = new BodyContentHandler();
Metadata metadata = new Metadata();
PDFParser pdfparser = new PDFParser();

Extract text from a PDF using Apache Tika 788


Real's HowTo PDF version

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.

Detect and remove blank page in pdf (iText)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-detect-and-remove-blank-page-in-pdf.html

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
re-test before setting this value!

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 com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.io.RandomAccessSourceFactory;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import 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

Detect and remove blank page in pdf (iText) 789


Real's HowTo PDF version

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

Detect and remove blank page in pdf (iText) 790


Real's HowTo PDF version

}
}

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 Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Detect and remove blank page in pdf (iText) 791


Security
java-security

Encrypt a password
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0400.html

Transmit a password with MessageDigest

Message digests are secure one-way hash functions that take arbitrary-sized data and output a fixed-length
hash value.

A One-way 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) {

Security 792
Real's HowTo PDF version

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
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("SHA-1");
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!

Encrypt a password 793


Real's HowTo PDF version

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.

In this HowTo, a key file is created during the encryption process if the specified key file is not found.

import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.util.Properties;
import java.util.Scanner;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class CryptoUtils {

Encrypt a password 794


Real's HowTo PDF version

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


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

Encrypt a password 795


Real's HowTo PDF version

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

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

Encrypt a password 796


Real's HowTo PDF version

}
}

Create a checksum
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0416.html

MD5 digests have been widely used in the software world to provide some assurance that a downloaded file
has not been altered. A user can compare a published MD5 sum with the checksum of a downloaded file.

import java.io.*;
import java.security.MessageDigest;

public class MD5Checksum {

public static byte[] createChecksum(String filename) throws


Exception
{
InputStream fis = new FileInputStream(filename);

byte[] buffer = new byte[1024];


MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
fis.close();
return complete.digest();
}

// see this How-to for a faster way to convert


// a byte array to a HEX string
public static String getMD5Checksum(String filename) throws Exception {
byte[] b = createChecksum(filename);
String result = "";
for (int i=0; i < b.length; i++) {
result +=
Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
}
return result;
}

public static void main(String args[]) {


try {
System.out.println(getMD5Checksum("apache-tomcat-5.5.17.exe"));
// output :
// 0bb2827c5eacf570b6064e24e0e6653b

Create a checksum 797


Real's HowTo PDF version

// ref :
// http://www.apache.org/dist/
// tomcat/tomcat-5/v5.5.17/bin
// /apache-tomcat-5.5.17.exe.MD5
// 0bb2827c5eacf570b6064e24e0e6653b *apache-tomcat-5.5.17.exe
}
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]");
}
}

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

Create a checksum 798


Real's HowTo PDF version

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.
import java.io.*;
import java.util.zip.CRC32;
import java.util.zip.Checksum;

Create a checksum 799


Real's HowTo PDF version

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 SHA-1 which is on 160-bits (MD5
is 128-bits). 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();

Create a checksum 800


Real's HowTo PDF version

return complete.digest();
}

// see this How-to for a faster way to convert


// a byte array to a HEX string
public static String getSHA1Checksum(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(getSHA1Checksum("c:/temp/isapi_redirect-1.2.30.dll"));
// output :
// cca9176f72ff56beb1f76c21b1d7daa6be192890
// ref :
// http://tomcat.apache.org/
// dev/dist/tomcat-connectors/
// jk/binaries/win32/jk-1.2.30/
// isapi_redirect-1.2.30.dll.sha1
//
// cca9176f72ff56beb1f76c21b1d7daa6be192890 *isapi_redirect-1.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.

Get the username


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

In application :

Get the username 801


Real's HowTo PDF version

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.

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 server-side,
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!

Get the username using NTLM from a JSP


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

Get the username using NTLM from a JSP 802


Real's HowTo PDF version

<%@ page import="sun.misc.BASE64Encoder" %>


<p><h1>Network Windows USERNAME without any login (ie)</h1></p>
<%
String auth = request.getHeader("Authorization");
if (auth == null) {
response.setStatus(response.SC_UNAUTHORIZED);
response.setHeader("WWW-Authenticate", "NTLM");
return;
}
if (auth.startsWith("NTLM ")) {
byte[] msg =
new sun.misc.BASE64Decoder().decodeBuffer(auth.substring(5));
int off = 0, length, offset;
String s;

if (msg[8] == 1) {
off = 18;

byte z = 0;
byte[] msg1 =
{(byte)'N', (byte)'T', (byte)'L', (byte)'M', (byte)'S',
(byte)'S', (byte)'P', z,
(byte)2, z, z, z, z, z, z, z,
(byte)40, z, z, z, (byte)1, (byte)130, z, z,
z, (byte)2, (byte)2, (byte)2, z, z, z, z, //
z, z, z, z, z, z, z, z};
//
response.setStatus(response.SC_UNAUTHORIZED);
response.setHeader("WWW-Authenticate", "NTLM "
+ new sun.misc.BASE64Encoder().encodeBuffer(msg1).trim());
return;
}
else if (msg[8] == 3) {
off = 30;
length = msg[off+17]*256 + msg[off+16];
offset = msg[off+19]*256 + msg[off+18];
s = new String(msg, offset, length);
//out.println(s + " ");
}
else
return;

length = msg[off+1]*256 + msg[off];


offset = msg[off+3]*256 + msg[off+2];
s = new String(msg, offset, length);
//out.println(s + " ");
length = msg[off+9]*256 + msg[off+8];
offset = msg[off+11]*256 + msg[off+10];
s = new String(msg, offset, length);
out.println("Hello <span style='position:relative; width:190;"
+ " height:10;filter:glow(Color=#009966,Strength=1)'>");
out.println(s + "</SPAN>");
}
%></BODY>

Get the username using NTLM from a JSP 803


Real's HowTo PDF version

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("[^a-zA-Z\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

Check if the current user belongs a specific Windows group/role


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../pbdetails/pb-0227.html

You can connect to the ActiveDirectory or use some API but an easy way is to use a connection to SQL
Server. Send the query :

SELECT is_member('mydomain\g_dept')

and the result can be

0 Current user is not a member of group or role.

1 Current user is a member of group or role.

NULL Either group or role is not valid.

Allow user:password in URL


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../pbdetails/pb-0249.html

The following URL syntax is no longer supported in Internet Explorer or in Windows Explorer after you
install the MS04-004 Cumulative Security Update for Internet Explorer (832894):

Check if the current user belongs a specific Windows group/role 804


Real's HowTo PDF version

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

Input password from the console


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0375.html

A separate thread is used to send to the console the backspace character to erase the last-typed character.

import java.io.*;
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");

Allow user:password in URL 805


Real's HowTo PDF version

System.out.println("Password: '" + pass + "'");


}
}

class ConsoleEraser extends Thread {


private boolean running = true;
public void run() {
while (running) {
System.out.print("\b ");
}
}

public synchronized void halt() {


running = false;
}
}

Java SE6 provides a buiilt-in mechanism to input a password from the console.

java.io.Console cons;
char[] passwd;
if ((cons = System.console()) != null &&

(passwd = cons.readPassword("[%s]", "Password:")) != null) {


...
}

Prevent XSS exploit


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

Input password from the console 806


Real's HowTo PDF version

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
• 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/simple-cross-site-scripting-xss-servlet-filter/.

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!

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.

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 :

Character Entity Code


< &lt;
> &gt;

Prevent XSS exploit 807


Real's HowTo PDF version

& &amp;
' &#039;
" &#034;
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>
<br />

With JSF, the tag <h:outputtext ... > provides the same protection.

Also see Java Edition of the OWASP ESAPI Toolkit

Display a simple username/password Dialog from an Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0128.html

NOTE: This way to authenticate a user is NOT secured at all since the required information is embedded in
the Applet.

[MyApplet.java]

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

public class MyApplet extends java.applet.Applet {

Display a simple username/password Dialog from an Applet 808


Real's HowTo PDF version

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

Display a simple username/password Dialog from an Applet 809


Real's HowTo PDF version

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


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>

Display a simple username/password Dialog from an Applet 810


Real's HowTo PDF version

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

Solve "Application blocked by security settings" message with


unsigned Applet
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-solve-application-blocked-by-security-settings-message.html

The Java plugin refuses to run unsigned applets, starting with version 1.7u51. It shows the message
"Application blocked by security settings", and no visible option to override this limitation.

To allow unsigned applets, you need to create a whitelist. If the unsigned applet is coming from one the
websites specified in the whitelist then its execution will be permitted.

Manually

The whitelist is simple text file called exception.sites containing one URL per line.

For example, to allow the unsigned applets from rgagnon.com to execute, the file exception.sites will have
this line :

http://www.rgagnon.com

This file must be located in the user's profile which is


%APPDATA%\Sun\Java\Deployment\security for XP, and
%USERPROFILE%\AppData\LocalLow\Sun\Java\Deployment\security for Win7. So if
you are on Win7, create the text file exception.sites with the required line for rgagnon.com as mentioned
above. Save the file in the directory C:\Users\*YOUR
USERNAME*\AppData\LocalLow\Sun\Java\Deployment\security.

Go to this page to do a test with an unsigned applet. You will still have one security popup to click before

Solve "Application blocked by security settings" message with unsigned Applet 811
Real's HowTo PDF version

running the applet.

Via the Java Control Panel

The Java Control Panel is not in the Control Panel of Windows any more, instead it is now in the Start
Menu as "Configure Java" (java).

Go to the security tab, click on the "Manage Site List"

Click on "add" for each site you want to add to exception list.

Solve "Application blocked by security settings" message withunsigned Applet 812


Real's HowTo PDF version

A global 'exception.sites' for all users

The above procedure can be cumbersome, especially in the enterprise environment since it is specific for
one user. It is easier to have one global whitelist and make sure that every users are using it.

You declare the common location of the exception list in "Deployment Properties" file located in
%windir%\Sun\Java\Deployment\deployment.properties. If this .properties file doesn't
exist then you need to create it.

You add one property called deployment.user.security.exception.sites, you specify the


complete path to the shared exception.sites file. Make sure to use "/" or "\\" as directory separator.

ex:

deployment.user.security.exception.sites=C:/Windows/Sun/Java/Deployment/exception.sites

This location can be on a network share if needed.

Note :
An interesting page on the subject with some possible issues for Firefox or Chrome.

Written and compiled Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Solve "Application blocked by security settings" message withunsigned Applet 813


String/Number
java-stringnumber

*Read me*
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0290.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.

Stack Overflow
A site where you can ask question (not restricted to Java), really innovative in the way it works. Participants
are really cool.

Convert from type X to type Y


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0004.html

integer to String :

int i = 42;
String str = Integer.toString(i);
or
String str = "" + i

double to String :

String str = Double.toString(i);

long to String :

String/Number 814
Real's HowTo PDF version

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 :

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

Convert from type X to type Y 815


Real's HowTo PDF version

Byte array to hexadecimal string:


See this How-to

hexadecimal (String) to integer :

int i = Integer.valueOf("B8DA3", 16).intValue();


or
int i = Integer.parseInt("B8DA3", 16);

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 :

try{
i = Integer.parseInt(aString);
}
catch(NumberFormatException e) {
...
}

Convert from type X to type Y 816


Real's HowTo PDF version

Strip certain characters from String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0018.html

This example keeps only a given set of accepted characters.

public class StringUtils {


private StringUtils() {}

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

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

NOTE: You may want to look at How-to optimize string operations

The following snippet will strip or keep from a given string the specified characters.

Thanks to T. GUIRADO for the idea

public class StringUtils {


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

Strip certain characters from String 817


Real's HowTo PDF version

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

Replace/remove character in a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0030.html

To replace all occurences of a given character :

String tmpString = myString.replace( '\'', '*' );

System.out.println( "Original = " + myString );


System.out.println( "Result = " + tmpString );

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 non-digit in a String

System.out.println(
"@*1#^2$@!34#5ajs67>?<{8_(9SKJDH".replaceAll("\\D", ""));

Replace/remove character in a String 818


Real's HowTo PDF version

// 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 How-to for String handling techniques.

Replace every occurences of a string within a string


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

Replace every occurences of a string within a string 819


Real's HowTo PDF version

[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.

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
}

Replace every occurences of a string within a string 820


Real's HowTo PDF version

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

"Tokenize" a string
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0015.html

import java.util.StringTokenizer;
...

StringTokenizer st =
new StringTokenizer
("This is the string to be tokenized", " ");

while(st.hasMoreTokens()){
String s=st.nextToken();
System.out.println(s);
}

/*
output is :
This
is
the

"Tokenize" a string 821


Real's HowTo PDF version

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.

"Tokenize" a string 822


Real's HowTo PDF version

*/
public EnhancedStringTokenizer(String str) {
setMode(this.NO_RETURN_DELIMS);
st = new StringTokenizer(str);
}

/**
* Same as the StringTokenizer constructor. No added functionality.
*/
public EnhancedStringTokenizer(String str, String delim){
setMode(this.NO_RETURN_DELIMS);
setDelimiter(delim);
st = new StringTokenizer(str, delim);
}

/**
* Same as the StringTokenizer constructor. No added functionality.
*/
public EnhancedStringTokenizer
(String str, String delim, boolean returnDelims) {
if (returnDelims) {
setMode(RETURN_DELIMS);
}
else {
setMode(NO_RETURN_DELIMS);
}
setDelimiter(delim);
st = new StringTokenizer(str, delim, returnDelims);
}

/**
* Using this constructor allows use of the NO_CONSECUTIVE_DELIMS mode
* of operation.
*/
public EnhancedStringTokenizer(String str, String delim, int mode) {
setMode(mode);
setDelimiter(delim);
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;
}
}

"Tokenize" a string 823


Real's HowTo PDF version

void init(String str) {


setRemainder(str);
}

public int countTokens() {


switch (getMode()) { {
case NO_CONSECUTIVE_DELIMS :
{
String oldRem = getRemainder();
int count = 0;
try {
String temp;
while (true) {
temp = nextToken();
count++;
}
}
catch (NoSuchElementException nsee) {
setRemainder(oldRem);
return count;
}
}
default :
return st.countTokens();
}
}

public boolean hasMoreElements() {


switch (getMode()) {
case NO_CONSECUTIVE_DELIMS :
int intIndex = 0;
intIndex =
getRemainder().indexOf(getDelimiter(), intIndex);
if (intIndex != -1) {
return true;
}
else {
if (getRemainder().length() > 0) {
return true;
}
else {
return false;
}
}
default :
return st.hasMoreElements();
}
}

public Object nextElement() throws NoSuchElementException {


switch (getMode()) {
case NO_CONSECUTIVE_DELIMS :
int intIndex = 0;
intIndex =

"Tokenize" a string 824


Real's HowTo PDF version

getRemainder().indexOf(getDelimiter(), intIndex);
if (intIndex != -1) {
String retValue =
getRemainder().substring(0, intIndex);
setRemainder(getRemainder().substring(intIndex + 1));
return retValue;
}
else {
if (getRemainder().length() > 0) {
String retValue = getRemainder();
setRemainder("");
return retValue;
}
else {
throw new NoSuchElementException();
}
}
default :
return st.nextElement();
}
}

public boolean hasMoreTokens() {


switch (getMode()) {
case NO_CONSECUTIVE_DELIMS :
int intIndex = 0;
intIndex =
getRemainder().indexOf(getDelimiter(), intIndex);
if (intIndex != -1) {
return true;
}
else {
if (getRemainder().length() > 0) {
return true;
}
else {
return false;
}
}
default :
return st.hasMoreElements();
}
}

public String nextToken() throws NoSuchElementException {


switch (getMode()) {
case NO_CONSECUTIVE_DELIMS :
int intIndex = 0;
intIndex =
getRemainder().indexOf(getDelimiter(), intIndex);
if (intIndex != -1) {
String retValue =
getRemainder().substring(0, intIndex);
setRemainder(getRemainder().substring(intIndex + 1));

"Tokenize" a string 825


Real's HowTo PDF version

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

"Tokenize" a string 826


Real's HowTo PDF version

Split a string using String.split()


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0438.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 = "Real-How-To";
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(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("\\|")));

Split a string using String.split() 827


Real's HowTo PDF version

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

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 : []

Split a string using String.split() 828


Real's HowTo PDF version

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

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}{java-0438.html}{usage of String.split()}";
System.out.println
(java.util.Arrays.toString(testString.split("[{}]")));
// output : [, RealHowto, , java-0438.html, , usage of String.split()]
// note : extra empty elements :-(

Split a string using String.split() 829


Real's HowTo PDF version

To split a long string into into fixed-length 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!java-0438.html!usage of String.split()!";
System.out.println
(java.util.Arrays.toString(testString.split("(?<=[!])")));
// output : [RealHowto!, java-0438.html!, usage of String.split()!]

Optimize String operations


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0129.html

(thanks to B. Wilkinson)
String concatenation via the "+" operator is one of the most convenient things to do in Java. It is also one of
the most expensive, in terms of memory and performance.

When the compiler sees

String s = "abc" + someint + somearray[index];

or any other concatenation, it **ACTUALLY** generates (for runtime use) the code sequence that follows
(or, at least, the bytecode equivalent of it):

StringBuffer temp = new StringBuffer( );


temp.append( String.valueOf( "abc" ) );
temp.append( String.valueOf( someInt ) );
temp.append( String.valueOf( someArray[index] );
String s = temp.toString( );

The weak spot in all this is the construction of the StringBuffer object: the size of the buffer is ALWAYS 16
characters. Then, as data is appended to the buffer, if more space is needed the size of the buffer is doubled
and the old data is copied to the new buffer.

So to optimize we have to bypass the automatic StringBuffer when possible. In this JAVA How-to, a snippet
is given to replace a character at a specific position. An optimized version, using the StringBuffer would be:

public static String replaceCharAt(String s, int pos, char c) {


StringBuffer buf = new StringBuffer( s );
buf.setCharAt( pos, c );
return buf.toString( );
}

Optimize String operations 830


Real's HowTo PDF version

Only one buffer created, exactly the right size. Converting a StringBuffer to a String costs almost nothing, as
the actual buffer is shared between the two.

In the same How-to, a snippet about removing a character in a String can be optimized like:

public static String removeChar(String s, char c) {


StringBuffer r = new StringBuffer( s.length() );
r.setLength( s.length() );
int current = 0;
for (int i = 0; i < s.length(); i ++) {
char cur = s.charAt(i);
if (cur != c) r.setCharAt( current++, cur );
}
return r.toString();
}

In the original version, a new String object was created and discarded immediately!

The weak spot of the original method to remove a character is when the parameter s passed havee than 17
characters, the temporary StringBuffer created by the compiler will have to be extended. To optimize, simply
rewrite the method using a StringBuffer with the correct size:

public static String removeCharAt(String s, int pos) {


StringBuffer buf = new StringBuffer( s.length() - 1 );
buf.append( s.substring(0,pos) ).append( s.substring(pos+1) );
return buf.toString();
}

Check this nice article about String/StringBuffer optimization.

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 single-thread context) than

StringBuilder sb = new StringBuilder(300);


for (int i = 0; i < 100; i++) {
sb.append(i).append('\n');
}

Optimize String operations 831


Real's HowTo PDF version

Remove spaces from a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0352.html

Remove all spaces

public String removeSpaces(String s) {


StringTokenizer st = new StringTokenizer(s," ",false);
String t="";
while (st.hasMoreElements()) t += st.nextElement();
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+", "");
}

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

Remove spaces from a String 832


Real's HowTo PDF version

public static void main(String[] args){


String oldStr =
"------[1-2-1-2-1-2-1-2-1-2-1-----2-1-2-1-2-1-2-1-2-1-2-1-2]----";
String newStr = oldStr.replaceAll("-", " ");
System.out.println(newStr);
System.out.println("*" + 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!

Test if a String starts with a digit or uppercase letter


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0430.html

With JDK1.4, regex expression can be handled directly.

import java.util.regex.Pattern;
...
boolean startsWithDigitOrUpper(String s) {
return Pattern.compile("^[A-Z0-9]").matcher(s).find();
}

Get InputStream from a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0442.html

public static final String ENCODING = "UTF8"; // see note

public static InputStream fromString(String str) {


byte[] bytes = str.getBytes(ENCODING);
return new ByteArrayInputStream(bytes);

Test if a String starts with a digit or uppercase letter 833


Real's HowTo PDF version

Note : List of supported encodings here

Easy String padding


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

Howto *
Howto*

*/
}

These one-liners 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

Get InputStream from a String 834


Real's HowTo PDF version

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);
char[] ch = new char[add];
Arrays.fill(ch, c);
if(paddingLeft){
str.insert(0, ch);
}
else {
str.append(ch);
}
return str.toString();
}

Easy String padding 835


Real's HowTo PDF version

Thanks to P. Buluschek for this snippet.

Replace \r\n with the <br> tag


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0454.html

This can be done easily a regular expression.

[JDK1.4]

import java.util.regex.Pattern;
import java.util.regex.Matcher;

...
// 4 different combinaisons
Pattern CRLF = Pattern.compile("(\r\n|\r|\n|\n\r)");
Matcher m = CRLF.matcher(myString);

if (m.find()) {
newString = m.replaceAll("<br>");
}

or use the String.replaceAll(regex,replacement) method which is doing basically the same thing.

newString = myString.replaceAll("(\r\n|\r|\n|\n\r)", "<br>");

Remove accent from letters (ex .é to e)


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

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 US-ASCII characters.

import java.text.Normalizer;

Replace \r\n with the <br> tag 836


Real's HowTo PDF version

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 _ @
}
}

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.replaceAll("[èéêë]","e");
s = s.replaceAll("[ûù]","u");
s = s.replaceAll("[ïî]","i");
s = s.replaceAll("[àâ]","a");
s = s.replaceAll("Ô","o");

s = s.replaceAll("[ÈÉÊË]","E");
s = s.replaceAll("[ÛÙ]","U");
s = s.replaceAll("[ÏÎ]","I");
s = s.replaceAll("[ÀÂ]","A");
s = s.replaceAll("Ô","O");

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

The String.indexOf()

While the two techniques above are ok... there are a little bit slow.

Remove accent from letters (ex .é to e) 837


Real's HowTo PDF version

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 :

Remove accent from letters (ex .é to e) 838


Real's HowTo PDF version

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

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

Remove accent from letters (ex .é to e) 839


Real's HowTo PDF version

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

Apply a mask to a string


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0457.html

JDK1.4

public class TestMF {


public static String value = "A1234B567Z";
public static String mask = "A-AAAA-AAAA-A";

public static void main(String args[]) {


try {
System.out.println(formatString(value,mask));
// output : A-1234-B567-Z
}
catch (java.text.ParseException e) {
e.printStackTrace();
}
}

public static String formatString(String string, String mask)


throws java.text.ParseException {
javax.swing.text.MaskFormatter mf =
new javax.swing.text.MaskFormatter(mask);
mf.setValueContainsLiteralCharacters(false);
return mf.valueToString(string);
}
}

NOTE : Since this is Swing class, it is designed to be used in conjunction with a JFormattedTextField.

MaskFormatter format = new MaskFormatter("A##-##");


JFormattedTextField textField = new JFormattedTextField( format );
textField.setFocusLostBehavior(JFormattedTextField.COMMIT);

Apply a mask to a string 840


Real's HowTo PDF version

The possible mask values are

Character Description
# Any valid number, uses Character.isDigit .
' Escape character, used to escape any of
the special formatting characters.
U Any character ( Character.isLetter ).
All lowercase letters are mapped to upper case.
L Any character ( Character.isLetter ).
All upper case letters are mapped to lower case.
A Any character or number
( Character.isLetter or Character.isDigit )
? Any character ( Character.isLetter ).
* Anything.
H Any hex character (0-9, a-f or A-F).

Format a String (JDK1.5)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0463.html

JDK1.5 simplifies the operation of formatting a String based on parameters.

The String class now provides a new method called format(). The parameter substitution mechanism is
heavily inspired by C's printf.

String s = String.format
("Welcome %s at %s", "Real's HowTo", "http://www.rgagnon.com");
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()};

Format a String (JDK1.5) 841


Real's HowTo PDF version

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

Output:

|FirstName |Init. |LastName |


|Real | |Gagnon |
|John |D |Doe |
|John |F. |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

Replace a "\" by "\\"


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0476.html

It can be quite an adventure to deal with the "\" since it is considered as an escape character in Java. You
always need to "\\" a "\" in a String. But the fun begins when you want to use a "\" in regex expression,

Replace a "\" by "\\" 842


Real's HowTo PDF version

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.

Substitute tokens in a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0494.html

Object[] params = new Object[]{"hello", "!"};


String msg = MessageFormat.format("{0} world {1]", params);
// hello world !

java.text.MessageFormat is a very powerful API, you should study the javadoc to see all the possibilities.

Compare accentuated letters


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

Substitute tokens in a String 843


Real's HowTo PDF version

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

Compare accentuated letters 844


Real's HowTo PDF version

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 = "Réal";

System.out.println(a + " and " + b + " equals? " +


check(a,b));
/*
* output :
* Real and Réal equals? true
*/
}

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.

Create a String with a fixed length


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0512.html

public class StringFixedAndFilled {


public static void main(String argv[]) {
String s = ">" + fillString('X', 25) + "<";
System.out.println(s);
s = ">" + fillString(' ', 25) + "<";
System.out.println(s);
/*
output : >XXXXXXXXXXXXXXXXXXXXXXXXX<
> <
*/

Create a String with a fixed length 845


Real's HowTo PDF version

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

Unquote a String
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0522.html

We use the fact that the Properties unquote a String, so we simply simulate a Property read with our String.

Maybe not the best way but it is certainly very easy!

import java.io.*;
import java.util.*;

public class Unquote {


public static void main(String[] args) {
String a = "Visit Real\\'s at http://www.rgagnon.com";
System.out.println(a);
String b = unquote(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");
}
}

Escape HTML special characters from a String

Unquote a String 846


Real's HowTo PDF version

Current version of this HowTo :


http://www.rgagnon.com/javadetails/../javadetails/java-0306.html

public static final String escapeHTML(String s){


StringBuffer sb = new StringBuffer();
int n = s.length();
for (int i = 0; i <n; i++) {
char c = s.charAt(i);
switch (c) {
case '<': sb.append("&lt;"); break;
case '>': sb.append("&gt;"); break;
case '&': sb.append("&amp;"); break;
case '"': sb.append("&quot;"); break;
case 'à': sb.append("&agrave;");break;
case 'À': sb.append("&Agrave;");break;
case 'â': sb.append("&acirc;");break;
case 'Â': sb.append("&Acirc;");break;
case 'ä': sb.append("&auml;");break;
case 'Ä': sb.append("&Auml;");break;
case 'å': sb.append("&aring;");break;
case 'Å': sb.append("&Aring;");break;
case 'æ': sb.append("&aelig;");break;
case 'Æ': sb.append("&AElig;");break;
case 'ç': sb.append("&ccedil;");break;
case 'Ç': sb.append("&Ccedil;");break;
case 'é': sb.append("&eacute;");break;
case 'É': sb.append("&Eacute;");break;
case 'è': sb.append("&egrave;");break;
case 'È': sb.append("&Egrave;");break;
case 'ê': sb.append("&ecirc;");break;
case 'Ê': sb.append("&Ecirc;");break;
case 'ë': sb.append("&euml;");break;
case 'Ë': sb.append("&Euml;");break;
case 'ï': sb.append("&iuml;");break;
case 'Ï': sb.append("&Iuml;");break;
case 'ô': sb.append("&ocirc;");break;
case 'Ô': sb.append("&Ocirc;");break;
case 'ö': sb.append("&ouml;");break;
case 'Ö': sb.append("&Ouml;");break;
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;

Escape HTML special characters from a String 847


Real's HowTo PDF version

// be carefull with this one (non-breaking whitee space)


case ' ': sb.append("&nbsp;");break;

default: sb.append(c); break;


}
}
return sb.toString();
}

Here another snippet to convert a String to HTML. This one is little bit better because it deals with space
versus non-breaking space (&nbsp;) and Unicode characters.

Submitted by S. Bayer. (PS. Thanks to ablage_p for the fix!)

public static String stringToHTMLString(String string) {


StringBuffer sb = new StringBuffer(string.length());
// true if last char was blank
boolean lastWasBlankChar = false;
int len = string.length();
char c;

for (int i = 0; i < len; i++)


{
c = string.charAt(i);
if (c == ' ') {
// blank gets extra work,
// this solves the problem you get if you replace all
// blanks with &nbsp;, if you do that you loss
// word breaking
if (lastWasBlankChar) {
lastWasBlankChar = false;
sb.append("&nbsp;");
}
else {
lastWasBlankChar = true;
sb.append(' ');
}
}
else {
lastWasBlankChar = false;
//
// HTML Special Chars
if (c == '"')
sb.append("&quot;");
else if (c == '&')
sb.append("&amp;");
else if (c == '<')
sb.append("&lt;");
else if (c == '>')
sb.append("&gt;");
else if (c == '\n')
// Handle Newline
sb.append("&lt;br/&gt;");

Escape HTML special characters from a String 848


Real's HowTo PDF version

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

Unescape HTML special characters from a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0307.html

Using HashMap

import java.util.*;

public class StringUtils {

private StringUtils() {}

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;","ù");

Unescape HTML special characters from a String 849


Real's HowTo PDF version

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

Unescape HTML special characters from a String 850


Real's HowTo PDF version

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 Réal Gagnon <www.rgagnon.com>
*/
}
}

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;" , "ù" } ,
{ "&Ugrave;" , "Ù" } , { "&ucirc;" , "û" } ,
{ "&Ucirc;" , "Û" } , { "&uuml;" , "ü" } ,
{ "&Uuml;" , "Ü" } , { "&nbsp;" , " " } ,

Unescape HTML special characters from a String 851


Real's HowTo PDF version

{ "&copy;" , "\u00a9" } ,
{ "&reg;" , "\u00ae" } ,
{ "&euro;" , "\u20a0" }
};

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 Réal Gagnon <www.rgagnon.com>
*/
}
}

Unescape HTML special characters from a String 852


Real's HowTo PDF version

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_HTML.

Detect non-ASCII character in a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0536.html

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharacterCodingException;

public class StringUtils {


private StringUtils() {}

public static boolean isPureAscii(String v) {


byte bytearray [] = v.getBytes();
CharsetDecoder d = Charset.forName("US-ASCII").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 = "Réal";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));
test = "Real";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));
/*
* output :
* Réal 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;

Detect non-ASCII character in a String 853


Real's HowTo PDF version

public class StringUtils {

static CharsetEncoder asciiEncoder =


Charset.forName("US-ASCII").newEncoder(); // or "ISO-8859-1" for ISO Latin 1

public static boolean isPureAscii(String v) {


return asciiEncoder.canEncode(v);
}

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


String test = "Réal";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));
test = "Real";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));

/*
* output :
* Réal isPureAscii() : false
* Real isPureAscii() : true
*/
}
}

Another way is to use a regular expression, see this Javascript HowTo for a hint!

To simply strip any non-ascii characters form a string


public class Test {
public static void main(String args[]){
String input = "eéaà";
String output = input.replaceAll("[^\\p{ASCII}]", "");
System.out.println(output);
/*
* output : ea
*/
}
}

See also Unaccent letters.

Remove HTML tags from a file to extract only the TEXT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0424.html

Using regular expression

A special regular expression is used to strip out anything between a < and > .

Remove HTML tags from a file to extract only the TEXT 854
Real's HowTo PDF version

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("java-new.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.

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 java.io.IOException;
import java.io.FileReader;
import java.io.Reader;
import java.util.List;
import java.util.ArrayList;

import javax.swing.text.html.parser.ParserDelegator;
import javax.swing.text.html.HTMLEditorKit.ParserCallback;
import javax.swing.text.html.HTML.Tag;
import 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) { }

Remove HTML tags from a file to extract only the TEXT 855
Real's HowTo PDF version

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("java-new.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 well-formed.

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;
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/java-language.html");
System.out.println(HTMLUtils.extractText(reader));
}
}

Remove HTML tags from a file to extract only the TEXT 856
Real's HowTo PDF version

Using Apache Tika

Apache Tika

import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.BodyContentHandler;
import org.xml.sax.ContentHandler;

public class ParseHTMLWithTika {


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

InputStream is = null;
try {

is = new FileInputStream("C:/Temp/java-x.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

Extract links from an HTML page


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0639.html

Remove HTML tags from a file to extract only the TEXT 857
Real's HowTo PDF version

Using javax.swing.text.html.HTMLEditorKit

import java.io.IOException;
import java.io.FileReader;
import java.io.Reader;
import java.util.List;
import java.util.ArrayList;

import javax.swing.text.html.parser.ParserDelegator;
import javax.swing.text.html.HTMLEditorKit.ParserCallback;
import javax.swing.text.html.HTML.Tag;
import javax.swing.text.html.HTML.Attribute;
import 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("java-new.html");
List<String> links = HTMLUtils.extractLinks(reader);
for (String link : links) {
System.out.println(link);
}
}
}

Using an HTML parser

In this HowTo, I will use the OpenSource package Jsoup.

import java.io.IOException;
import java.util.List;

Extract links from an HTML page 858


Real's HowTo PDF version

import java.util.ArrayList;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import 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/java-language.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.

Convert a byte array to a Hex string


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0596.html

Convert a byte array to a Hex string 859


Real's HowTo PDF version

The simple way

public static String getHexString(byte[] b) throws Exception {


String result = "";
for (int i=0; i < b.length; i++) {
result +=
Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
}
return result;
}

A faster way

import java.io.UnsupportedEncodingException;

public class StringUtils {

static final byte[] HEX_CHAR_TABLE = {


(byte)'0', (byte)'1', (byte)'2', (byte)'3',
(byte)'4', (byte)'5', (byte)'6', (byte)'7',
(byte)'8', (byte)'9', (byte)'a', (byte)'b',
(byte)'c', (byte)'d', (byte)'e', (byte)'f'
};

private StringUtils () {}

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];
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
*/

Convert a byte array to a Hex string 860


Real's HowTo PDF version

}
}

A more elegant (based on a suggestion by Lew on usenet-cljp)

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

Apply proper uppercase and lowercase on a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0594.html

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringUtils {


private StringUtils () {}

public static String upperCaseWordFirst(String str) {


StringBuffer sb = new StringBuffer();
Matcher m = Pattern.compile
("([a-z])([a-z]*)",Pattern.CASE_INSENSITIVE).matcher(str);
while (m.find()) {
m.appendReplacement(sb, m.group(1).toUpperCase()
+ m.group(2).toLowerCase()) ;
}
str = m.appendTail(sb).toString();
return str;
}

public static void main(String [] args) {


System.out.println(StringUtils.upperCaseWordFirst(" #600how-to"));
System.out.println(StringUtils.upperCaseWordFirst("ELVis preSLEY"));
System.out.println(StringUtils.upperCaseWordFirst("john o'connor & steeve mcmillan"));
/*
output :

#600How-To

Apply proper uppercase and lowercase on a String 861


Real's HowTo PDF version

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...
*/
}
}

Encode/Decode to/from Base64


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0598.html

As seen in this HowTo, the sun.misc.BASE64Encoder/Decoder or creating your own Base64 handling are the
more common way to deal with Base64 encoding/decoding.

Here some alternatives which are maybe easier (and safer) to use.

Using javax.mail.internet.MimeUtility

import javax.mail.internet.MimeUtility;
import java.io.*;

public class Base64Utils {

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

Encode/Decode to/from Base64 862


Real's HowTo PDF version

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

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

Encode/Decode to/from Base64 863


Real's HowTo PDF version

MiGBase64

MiGBase64 is a very fast Base64 Codec written in Java. http://migbase64.sourceforge.net/.

Justify string with wordwrap


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0013.html

public class StringUtils {

private StringUtils() {}

/*
justify a string,
here only left justification is implemented
*/
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 ";

Encode/Decode to/from Base64 864


Real's HowTo PDF version

formatted_string = StringUtils.justifyLeft(25,original_string);

System.out.println("---------");
System.out.println(original_string);
System.out.println("---------");
System.out.println(formatted_string);
/*
output :
---------
01234567890123456789 01234567890 0123 4565789
---------
01234567890123456789
01234567890 0123
4565789
*/
}
}

Shorten a long path


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

Justify string with wordwrap 865


Real's HowTo PDF version

public static final int DEFAULT_SHORTENER_THRESHOLD = 4;


public static final String SHORTENER_BACKSLASH_REGEX = "\\\\";
public static final String SHORTENER_SLASH_REGEX = "/";
public static final String SHORTENER_BACKSLASH = "\\";
public static final String SHORTENER_SLASH = "/";
public static final String SHORTENER_ELLIPSE = "...";

private FileUtils() { }

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

if (elem > threshold) {


StringBuilder sb = new StringBuilder();
int index = 0;

// drive or protocol
int pos2dots = path.indexOf(":");
if (pos2dots > 0) {

Shorten a long path 866


Real's HowTo PDF version

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

Shorten a long path 867


Real's HowTo PDF version

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] ;
}
}
return new String(shortPathArray);
}

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


String t = "C:\\Documents and Settings\\All Users\\Application Data\\Apple Computer\\iTunes
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));

Shorten a long path 868


Real's HowTo PDF version

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.tx
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.

Ellipse a long string


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

Ellipse a long string 869


Real's HowTo PDF version

private StringUtils() { }

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.

Display an ASCII banner


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-display-ascii-banner.html

Draw a string to an Image and then examine the Image created and output " ", "#" or "*" depending of the
pixel value.

import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class AsciiBanner {

Display an ASCII banner 870


Real's HowTo PDF version

public static void main (String ... args) throws IOException {


// need to adjust for width and height
BufferedImage image = new BufferedImage(144, 32, BufferedImage.TYPE_INT_RGB);
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);
// the banner text may affect width and height
graphics.drawString("Real's HowTo", 6, 24);
ImageIO.write(image, "png", File.createTempFile("AsciiBanner.png", null));

// need to adjust for width and height


for (int y = 0; y <32; y++) {
StringBuilder sb = new StringBuilder();
// need to adjust for width and height
for (int x = 0; x <144; x++)
sb.append(image.getRGB(x, y) == -16777216 ? " " :
image.getRGB(x, y) == -1 ? "#" : "*");
if (sb.toString().trim().isEmpty()) continue;
System.out.println(sb);
}
}
}

Output is :

######*** ## ## ## ##
#########* ## ## ## ##
## **#* ## ** ## ##
## *#* ## ** ## ##
## *#* ******* ******* ## ** ****** ## ## ******* *#*
## **#* *#####** *######* ## *######* ## ## **#####** ***
########** *#** **#* *#****#* ## *#****#* ########### *#** **#* *#*
######*** *#* *#* #* ## *#* ########### *#* *#* *#*
## **** *#######* ****## ## *##**** ## ## *#* *#* *#*
## *#** *#######* **###### ## ***###** ## ## *# #* *#**
## *#* *#* *#****## ## ****#* ## ## *#* *#* ****
## *##* *#* *#* *## ## *#* ## ## *#* *#* *#*
## *#* *#** **#* *#* **##* ## *#****#* ## ## *#** **#* *#*
## **#* **#####** *#######* ## *######* ## ## **#####** *#
## *#* ******* *******#* ## ****** ## ## ******* *#

Convert from type X to type Y


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0004.html

integer to String :

Convert from type X to type Y 871


Real's HowTo PDF version

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 :

int i = 42;
String bin = Integer.toBinaryString(i);

decimal to hexadecimal :

int i = 42;
String hexstr = Integer.toString(i, 16);

Convert from type X to type Y 872


Real's HowTo PDF version

or
String hexstr = Integer.toHexString(i);

or (with leading zeroes and uppercase)


public class Hex {
public static void main(String args[]){
int i = 42;
System.out.print
(Integer.toHexString( 0x10000 | i).substring(1).toUpperCase());
}
}

Byte array to hexadecimal string:


See this How-to

hexadecimal (String) to integer :

int i = Integer.valueOf("B8DA3", 16).intValue();


or
int i = Integer.parseInt("B8DA3", 16);

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 :

Convert from type X to type Y 873


Real's HowTo PDF version

try{
i = Integer.parseInt(aString);
}
catch(NumberFormatException e) {
...
}

Type conversion (JDK1.5)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0464.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; // mix Integer and ints


System.out.println(i);

// output :
// 1
// 4
}
}

In the next example, a boolean is being stored and then retrieved from an ArrayList. The 1.5 version leaves
the conversion required to transition to an Boolean and back to the compiler.

import java.util.Collection.*;
import java.util.*;

public class Test15 {


public static void main(String ... args) {
ArrayList<Boolean> list = new ArrayList<Boolean>();
list.add(0, true);
boolean flag = list.get(0);
System.out.println(flag);
}
}

The old way (pre 1.5) is more cryptic...

import java.util.Collection.*;
import java.util.*;

Type conversion (JDK1.5) 874


Real's HowTo PDF version

public class Test15 {


public static void main(String args[]) {
ArrayList list = new ArrayList();
list.add(0, new Boolean(true));
boolean flag = ((Boolean)list.get(0)).booleanValue();
System.out.println(flag);
}
}

Note : To be able to compile that code with the JDK1.5, you need to specify the switch -source 1.4 on the
javac command line.

Round a double
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0016.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 args[]){
double d = 3.1537;
// output is 3.2
System.out.println(d + " : " + round(d, 1));
// output is 3.15
System.out.println(d + " : " + round(d, 2));
// output is 3.154

Round a double 875


Real's HowTo PDF version

System.out.println(d + " : " + round(d, 3));


d= 9.155;
// output is 9.2
System.out.println(d + " : " + round(d, 1));
// output is 9.16
System.out.println(d + " : " + round(d, 2));
// output is 3.155
System.out.println(d + " : " + round(d, 3));
d= 1234.156789;
// output is 1234.2
System.out.println(d + " : " + round(d, 1));
// output is 1234.16
System.out.println(d + " : " + round(d, 2));
// output is 1234.157
System.out.println(d + " : " + round(d, 3));
// output is 1234.1568
System.out.println(d + " : " + round(d, 4));
d= 1.5;
// output is 2
System.out.println(d + " : " + 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;
}
}

Display numbers with commas


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0019.html

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

Display numbers with commas 876


Real's HowTo PDF version

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

Display numbers in scientific notation


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0020.html

JDK1.0.2

public static String toScientific(double num,int places) {


String result="";
String sign="";

double power=(int)(Math.log(num)/Math.log(10));
if(power < 0) power--;
double fraction=num/Math.pow(10,power);
fraction=round(fraction,places);
if(power > 0) sign="+";
result += fraction + "e" + sign + power;
return result;
}

public static double round(double value, int decimalPlace) {

Display numbers with commas 877


Real's HowTo PDF version

double power_of_ten = 1;
while (decimalPlace-- > 0) power_of_ten *= 10.0;
return Math.round(value * power_of_ten) / power_of_ten;
}

JDK1.2+

A much better way is now in the java.text package :

import java.text.*;
import java.math.*;

public class TestScientific {

public static void main(String args[]) {


new TestScientific().doit();
}

public void doit() {


NumberFormat formatter = new DecimalFormat();

int maxinteger = Integer.MAX_VALUE;


System.out.println(maxinteger); // 2147483647

formatter = new DecimalFormat("0.######E0");


System.out.println(formatter.format(maxinteger)); // 2,147484E9

formatter = new DecimalFormat("0.#####E0");


System.out.println(formatter.format(maxinteger)); // 2.14748E9

int mininteger = Integer.MIN_VALUE;


System.out.println(mininteger); // -2147483648

formatter = new DecimalFormat("0.######E0");


System.out.println(formatter.format(mininteger)); // -2.147484E9

formatter = new DecimalFormat("0.#####E0");


System.out.println(formatter.format(mininteger)); // -2.14748E9

double d = 0.12345;
formatter = new DecimalFormat("0.#####E0");
System.out.println(formatter.format(d)); // 1.2345E-1

formatter = new DecimalFormat("000000E0");


System.out.println(formatter.format(d)); // 12345E-6
}
}

Display numbers in scientific notation 878


Real's HowTo PDF version

Display numbers with leading zeroes


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0021.html

jdk1.5+

Using String.format()

public class NumberUtils {


private 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

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


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

Display numbers with leading zeroes 879


Real's HowTo PDF version

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


System.out.println(NumberUtils.formatLong(123456L, 10));
// output : 0000123456
}
}

pre-jdk1.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
}
}

Get a random number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0017.html

JDK1.1, Random.nextInt() returns the next pseudorandom, uniformly distributed int value from this random
number generator's sequence.

// random number between 0 AND 10


import java.util.Random;

Random r = new Random();


int randint = Math.abs(r.nextInt()) % 11;

JDK1.2, Random.nextInt(n) returns a pseudorandom, uniformly distributed int value between 0 (inclusive)
and n (exclusive).

// random number between 0 AND 10


import java.util.Random;

Random r = new Random();


int randint = r.nextInt(10);

Convert an UNSIGNED byte to a JAVA integer


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0026.html

Display numbers with leading zeroes 880


Real's HowTo PDF version

In JAVA, a byte always considered as signed when converted to another type. We must mask the sign bit to
JAVA, cast to an integer and process the masked bit if needed. The following method implements this idea :

public class UnsignedByte {


public static void main (String args[]) {
byte b1 = 127;
byte b2 = -128;
byte b3 = -1;

System.out.println(b1);
System.out.println(b2);
System.out.println(b3);
System.out.println(unsignedByteToInt(b1));
System.out.println(unsignedByteToInt(b2));
System.out.println(unsignedByteToInt(b3));
/*
127
-128
-1
127
128
255
*/
}

public static int unsignedByteToInt(byte b) {


return (int) b & 0xFF;
}
}

Therefore for an array of 4 bytes (buf[]), which represents an integer :

int i = 0;
int pos = 0;
i += unsignedByteToInt(buf[pos++]) << 24;
i += unsignedByteToInt(buf[pos++]) << 16;
i += unsignedByteToInt(buf[pos++]) << 8;
i += unsignedByteToInt(buf[pos++]) << 0;

To convert a byte to it's hexadecimal equivalent

public static String byteToHex(byte b){


int i = b & 0xFF;
return Integer.toHexString(i);
}

NOTE: when converting byte representing an integer, it's possible that you will have to deal with the big-endian vs little-endian format. See this How-to

Convert an UNSIGNED byte to a JAVA integer 881


Real's HowTo PDF version

Deal with the big-endian and little-endian order


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0007.html

Java virtual machine always used big-endian, Intel x86 used little-endian.

public class Swab {


public final static int swabInt(int v) {
return (v >>> 24) | (v << 24) |
((v << 8) & 0x00FF0000) | ((v >> 8) & 0x0000FF00);
}

public static void main(String argv[]) {


// before 0x01020304
// after 0x04030201
int v = 0x01020304;
System.out.println("before : 0x" + Integer.toString(v,16));
System.out.println("after : 0x" + Integer.toString(swabInt(v),16));
}
}

NOTE: to convert UNSIGNED byte to integer, look at this How-to

Pass an integer by reference


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0035.html

Sometimes you may need to pass an integer to be able to change its value. "integer" are always passed by
value in Java. An easy way to pass by reference is to use a single element array.

int[] a = new int[1];


a[0] = 1;
add2(a);
// a[0] now = 3
...

void add2(int[] a) {
a[0] = a[0] + 2;
}

Pass floats as string literals to a method


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0050.html

Deal with the big-endian and little-endian order 882


Real's HowTo PDF version

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

Get random numbers


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0419.html

public class MyTest {


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

public void doit() {


java.util.Random rand = new java.util.Random();
// random integer 0 to 10
int max = 10;
for (int i=0; i<10; i++) {
System.out.println(rand.nextInt(max + 1));
}
// random double 0 to 10
double maxd = 10;
for (int i=0; i<10; i++) {
System.out.println(maxd * rand.nextDouble());
}
}
}

The output

4
0
0
10
10
4
10
10
6
10
8.13013058393518

Pass floats as string literals to a method 883


Real's HowTo PDF version

0.6631286078928067
4.382003543427801
7.2768144451559795
7.312852816962123
8.69257797289748
2.4967782036871657
4.451145854389913
1.82517092998838

Convert number to words


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0426.html

English

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

Get random numbers 884


Real's HowTo PDF version

" seventeen",
" eighteen",
" nineteen"
};

private EnglishNumberToWords() {}

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

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

Convert number to words 885


Real's HowTo PDF version

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;

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

Convert number to words 886


Real's HowTo PDF version

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

Français
Quite different than the english version but french is a lot more difficult!

package com.rgagnon.howto;

import java.text.*;

class FrenchNumberToWords {
private static final String[] dizaineNames = {
"",
"",
"vingt",

Convert number to words 887


Real's HowTo PDF version

"trente",
"quarante",
"cinquante",
"soixante",
"soixante",
"quatre-vingt",
"quatre-vingt"
};

private static final String[] uniteNames1 = {


"",
"un",
"deux",
"trois",
"quatre",
"cinq",
"six",
"sept",
"huit",
"neuf",
"dix",
"onze",
"douze",
"treize",
"quatorze",
"quinze",
"seize",
"dix-sept",
"dix-huit",
"dix-neuf"
};

private static final String[] uniteNames2 = {


"",
"",
"deux",
"trois",
"quatre",
"cinq",
"six",
"sept",
"huit",
"neuf",
"dix"
};

private FrenchNumberToWords() {}

private static String convertZeroToHundred(int number) {

int laDizaine = number / 10;


int lUnite = number % 10;
String resultat = "";

Convert number to words 888


Real's HowTo PDF version

switch (laDizaine) {
case 1 :
case 7 :
case 9 :
lUnite = lUnite + 10;
break;
default:
}

// séparateur "-" "et" ""


String laLiaison = "";
if (laDizaine > 1) {
laLiaison = "-";
}
// cas particuliers
switch (lUnite) {
case 0:
laLiaison = "";
break;
case 1 :
if (laDizaine == 8) {
laLiaison = "-";
}
else {
laLiaison = " et ";
}
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;

Convert number to words 889


Real's HowTo PDF version

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;
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 "zéro"; }

String snumber = Long.toString(number);

// pad des "0"


String mask = "000000000000";
DecimalFormat df = new DecimalFormat(mask);
snumber = df.format(number);

// XXXnnnnnnnnn
int lesMilliards = Integer.parseInt(snumber.substring(0,3));
// nnnXXXnnnnnn
int lesMillions = Integer.parseInt(snumber.substring(3,6));
// nnnnnnXXXnnn
int lesCentMille = Integer.parseInt(snumber.substring(6,9));
// nnnnnnnnnXXX
int lesMille = Integer.parseInt(snumber.substring(9,12));

String tradMilliards;
switch (lesMilliards) {

Convert number to words 890


Real's HowTo PDF version

case 0:
tradMilliards = "";
break;
case 1 :
tradMilliards = convertLessThanOneThousand(lesMilliards)
+ " milliard ";
break;
default :
tradMilliards = convertLessThanOneThousand(lesMilliards)
+ " milliards ";
}
String resultat = tradMilliards;

String tradMillions;
switch (lesMillions) {
case 0:
tradMillions = "";
break;
case 1 :
tradMillions = convertLessThanOneThousand(lesMillions)
+ " million ";
break;
default :
tradMillions = convertLessThanOneThousand(lesMillions)
+ " millions ";
}
resultat = resultat + tradMillions;

String tradCentMille;
switch (lesCentMille) {
case 0:
tradCentMille = "";
break;
case 1 :
tradCentMille = "mille ";
break;
default :
tradCentMille = convertLessThanOneThousand(lesCentMille)
+ " mille ";
}
resultat = resultat + tradCentMille;

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

Convert number to words 891


Real's HowTo PDF version

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
*** zéro
*** neuf
*** dix-neuf
*** vingt et un
*** vingt-huit
*** soixante et onze
*** soixante-douze
*** quatre-vingt
*** quatre-vingt-un
*** quatre-vingt-neuf
*** quatre-vingt-dix
*** quatre-vingt-onze
*** quatre-vingt-dix-sept
*** cent
*** cent un
*** cent dix
*** cent vingt
*** deux cents
*** deux cent un
*** deux cent trente-deux
*** neuf cent quatre-vingt-dix-neuf
*** mille
*** mille un
*** dix mille
*** dix mille un
*** cent mille
*** deux millions

Convert number to words 892


Real's HowTo PDF version

*** trois milliards


*** deux milliards cent quarante-sept millions
** quatre cent quatre-vingt-trois mille six cent quarante-sept
*/
}
}

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 built-in function of your DBMS (if available).

For Oracle

SQL> select to_char(to_date(873,'J'), 'JSP') as converted_form from dual;

CONVERTED_FORM
---------------------------
EIGHT HUNDRED SEVENTY-THREE

SQL>

'JSP' means :
• J : the Julian format.
• SP : spells the word for the number passed to to_date

Arithmetic with double


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0474.html

You may find that

System.out.println( 1.33 - 1.3 );


// output : 0.030000000000000027

The unexpected result is coming from the fact that internal floating-point number representation is not well
suited for that kind of operation.

Arithmetic with double 893


Real's HowTo PDF version

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

Detect even/odd number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0488.html

Use the modulus operator.

For Other interesting modulus operations, see http://mindprod.com/jgloss/modulus.html

if (x % 2 == 0) {
// even
}

if (x % 2 != 0) {
// odd
}

... or binary AND operator...

if (( x & 1 ) == 0) {
// even
}

if (( x & 1 ) != 0) {
// odd
}

Convert bytes to megabytes


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0540.html

import java .io.*;

public class Test {

public static void main(String args[]) {


// a big file ...
File f = new File("news.easynews.com.newsrc");

Detect even/odd number 894


Real's HowTo PDF version

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

Validate a number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0599.html

public class NumberUtils {

private NumberUtils() {}

// Check if given string is a number (digits only)


public static boolean isNumber(String string) {
return string.matches("^\\d+$");
}

// Check if given string is numeric (-+0..9(.)0...9)


public static boolean isNumeric(String string) {
return string.matches("^[-+]?\\d+(\\.\\d+)?$");
}

// Check if given string is number with dot separator and two decimals.
public static boolean isNumberWith2Decimals(String string) {
return string.matches("^\\d+\\.\\d{2}$");
}

public static void main(String[] args) {


System.out.println("42 valid ? " + NumberUtils.isNumber("42"));
System.out.println("42.1 valid ? " + NumberUtils.isNumber("42.1"));

System.out.println("42 valid ? " + NumberUtils.isNumeric("42"));


System.out.println("42.1 valid ? " + NumberUtils.isNumeric("42.1"));
System.out.println("-42.1 valid ? " + NumberUtils.isNumeric("42.1"));
System.out.println("-42.1a valid ? " + NumberUtils.isNumeric("42.1a"));

System.out.println("42.10 valid ? " + NumberUtils.isNumberWith2Decimals("42.10"));


System.out.println("42.101 valid ? " + NumberUtils.isNumberWith2Decimals("42.101"));
System.out.println("42,10 valid ? " + NumberUtils.isNumberWith2Decimals("42,10"));
System.out.println("42 valid ? " + NumberUtils.isNumberWith2Decimals("42"));

/*

Convert bytes to megabytes 895


Real's HowTo PDF version

* output
* 42.1 valid ? false
* 42 valid ? true
*
* 42.1 valid ? true
* -42.1 valid ? true
* -42.1a valid ? false
*
* 42.10 valid ? true
* 42.101 valid ? false
* 42,10 valid ? false
* 42 valid ? false
*/
}
}

Get a unique identifier


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0518.html

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

Validate a number 896


Real's HowTo PDF version

}
}

Output :

d578271282b42fce:-2955b56e:107df3fbc96:-8000
d578271282b42fce:-2955b56e:107df3fbc96:-7fff
d578271282b42fce:-2955b56e:107df3fbc96:-7ffe

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 : dedc3f57-6ce1-4504-a92f-640d8d9d23c9
}
}

This is probably the preferred method.

Mini-FAQ on the subject : http://www.asciiarmor.com/post/33736615/java-util-uuid-mini-faq

Using Apache commons

If you need compatibility with 1.4 then the org.apache.commons.id.uuid is an option.

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

public static long nextId() {


return nextId.getAndIncrement();
}
}

See also this HowTo for unique numerical id based on the system time.

Validate/Convert a number using the current Locale()


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0139.html

Get a unique identifier 897


Real's HowTo PDF version

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 {

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

Validate/Convert a number using the current Locale() 898


Real's HowTo PDF version

Transform a fraction to a Double


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-convert-fraction-to-double.html

import java.math.BigDecimal;
import java.math.MathContext;
import java.text.ParseException;

public class NumberUtils {

private 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"));
System.out.println(NumberUtils.fractionToDouble("4/5"));
System.out.println(NumberUtils.fractionToDouble("3/9"));

/*
* 0.5
* 0.6666666666666666
* 0.6666666666666666
* 0.8
* 0.3333333333333333
*/

Transform a fraction to a Double 899


Real's HowTo PDF version

}
}

Get short ordinal representation of a number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-get-short-ordinal-representation-of-a-number.html

import java.util.Locale;

public class NumberUtils {

private NumberUtils() { }

/*
* Ordinal (depends on the current locale)
* French or english support
*/
public static String getOrdinal(int number) {
if (Locale.getDefault().getLanguage().equals("fr")) {
return NumberUtils.getOrdinalFr(number);
}
else {
return NumberUtils.getOrdinalEn(number);
}
}

public static String getOrdinalFr(int number) {


if(number == 1 ) {
return number + "ier";
}
else {
return number + "e";
}
}

public static String getOrdinalEn(int number) {


int mod100 = number % 100;
int mod10 = number % 10;
if(mod10 == 1 && mod100 != 11) {
return number + "st";
}
else if(mod10 == 2 && mod100 != 12) {
return number + "nd";
}
else if(mod10 == 3 && mod100 != 13) {
return number + "rd";
} else {

Get short ordinal representation of a number 900


Real's HowTo PDF version

return number + "th";


}
}

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


int[] testCases = { 0, 1, 2, 3, 4, 5, 10,
11, 12, 13, 14, 20, 21, 22,
23, 24, 100, 101, 102, 103,
104, 1000, 1001, 1002 };
for (int testCase : testCases) {
System.out.println(NumberUtils.getOrdinal(testCase));
//System.out.println(NumberUtils.getOrdinalEn(testCase));
//System.out.println(NumberUtils.getOrdinalFr(testCase));

/*
output (english)
0th
1st
2nd
3rd
4th
5th
10th
11th
12th
13th
14th
20th
21st
22nd
...
*/
}
}
}

Written and compiled Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Get short ordinal representation of a number 901


Swing
java-swing

*Read me*
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0193.html

NOTE: With the JDK1.2 release, it's recommended to use

import javax.swing.*;

instead of

import com.sun.java.swing.*;

IE or Netscape don't support directly Swing Applet. You must use the Java plugins. Then you will need to use
the <OBJECT> (IE) or <EMBED> (Netscape) HTML tag instead of the regular <APPLET> tag.

Change default component font


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0335.html

public static void setUIFont (javax.swing.plaf.FontUIResource f){


//
// sets the default font for all Swing components.
// ex.
// setUIFont (new javax.swing.plaf.FontUIResource
// ("Serif",Font.ITALIC,12));
//
java.util.Enumeration keys = UIManager.getDefaults().keys();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
Object value = UIManager.get (key);
if (value instanceof javax.swing.plaf.FontUIResource)
UIManager.put (key, f);
}
}

For a particuliar component

Swing 902
Real's HowTo PDF version

UIManager.put("Label.font",new Font("Serif",Font.ITALIC,12));

Swing UI default

Repaint problem under the mouse cursor (JDK1.2)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0206.html

You probably have installed a Microsoft Theme on your desktop. Simply switch the mouse cursor to the
regular Windows mouse cursor to correct the problem.

Set the LookAndFeel


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0207.html

By default, Swing will use the Metal LookAndFeel. To set the LookAndFeel to the current OS under which
the JVM is running, use this snippet :

try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e) {
e.printStackTrace();
}

Even with the new naming mecanism in JDK1.2, some LookAndFeel packages are keeping the oldname.

Windows com.sun.java.swing.plaf.windows (no change)


Motif com.sun.java.swing.plaf.motif (no change)
Mac com.sun.java.swing.plaf.mac (no change)
Metal javax.swing.plaf.metal (new)
Basic javax.swing.plaf.basic (new)
Multi javax.swing.plaf.multi (new)
These packages are located in the rt.jar file.

Use any LookAndFeel on any plateform


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0208.html

Change default component font 903


Real's HowTo PDF version

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 non-Windows environment

java -Dos.name=windows MySwingApp

to activate Mac LookAndFeel on a non-Mac environment

java -Dos.name=mac MySwingApp

or you can do it in your source by doing something like:

Properties p = System.getProperties();
p.put("os.name", "Mac");
System.setProperties(p);

NOTE: Current Swing release for Windows does not include the necessary classes for the Mac's LookAndFeel anymore.

It's not bad idea to set the look and feel to a known good value and then try the not-so-sure value.

try {
// sure look and feel
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");

// not-so-sure look and feel


System.setProperty("os.name", "Windows");
System.setProperty("os.version", "5.1");
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
}
catch (Exception ex) {
ex.printStackTrace();
}

Use a Timer
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0220.html

See this How-to.

Use any LookAndFeel on any plateform 904


Real's HowTo PDF version

Share ActionEvent handler


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0212.html

In this example, a JMenu, JToolbar and JButtons on a JFrame are sharing common ActionEvent handlers.

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

public class ShareAction extends JFrame {


OpenAction openAction = new OpenAction();
SaveAction saveAction = new SaveAction();
QuitAction quitAction = new QuitAction();

public static void main(String argv[]) {


new ShareAction().setVisible(true);
}

ShareAction() {
createMenu();
createToolBar();
createButtons();
pack();

// deal closing via the upper right "X" by redirecting to


// quitAction
addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
ActionEvent ae =
new ActionEvent (quitAction,
ActionEvent.ACTION_PERFORMED,
"bebye");
JFrame j = (JFrame)e.getSource();
j.dispatchEvent(ae);
}
}
);
}

public Dimension getPreferredSize() {


return new Dimension(300,300);
}

private void createMenu(){


JMenuBar mb = new JMenuBar();
JMenu file = new JMenu("File");
mb.add(file);
file.add(openAction);

Share ActionEvent handler 905


Real's HowTo PDF version

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

Share ActionEvent handler 906


Real's HowTo PDF version

}
}

Get default values for Swing-based user interface


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0507.html

This little class will dump to stdout the default values used by Swing. You can redirect the result to a file with

>java UIDefaults > swing.props

import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import javax.swing.UIManager;

public class UIDefaults {


public static void main(String[] args) {
try {
Set defaults = UIManager.getLookAndFeelDefaults().entrySet();
// this TreeSet will hold the sorted properties
TreeSet ts = new TreeSet(new Comparator() {
public int compare(Object a, Object b) {
Map.Entry ea = (Map.Entry) a;
Map.Entry eb = (Map.Entry) b;
return
((String) ea.getKey()).compareTo(((String)eb.getKey()));
}
});
ts.addAll(defaults);
for (Iterator i = ts.iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
System.out.print(entry.getKey() + " = " );
System.out.println(entry.getValue());
}

} catch (Exception ex) {


ex.printStackTrace();
}
}
}

• For an example on how to change a default value see this HowTo


• To change a value for a particuliar component, see this HowTo
• Here a sample list for JavaUIDefaults

Get default values for Swing-based user interface 907


Real's HowTo PDF version

Have a systray icon (Windows)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0612.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 java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import 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);

Have a systray icon (Windows) 908


Real's HowTo PDF version

MenuItem exitItem = new MenuItem("Exit");


exitItem.addActionListener(exitListener);
menu.add(exitItem);
return menu;
}

/**
* 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 built-in icon
* (may not work with some LAF or built-in icon, use with caution!)
* 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();

Have a systray icon (Windows) 909


Real's HowTo PDF version

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

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 built-in icon in the JDK.

Close a JFrame under condition


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0340.html

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

public class CloseOrNot extends JFrame {

JTextField field1;

Close a JFrame under condition 910


Real's HowTo PDF version

JPanel panel;

public CloseOrNot() {
super( "CloseOrNot Frame" );
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
panel = new JPanel();
field1 = new JTextField( 10 );
panel.add( new JLabel("type yes to close the Frame "));
panel.add( field1 );
getContentPane().add( "Center", panel );
addWindowListener( new WindowAdapter() {
public void windowOpened( WindowEvent e ){
field1.requestFocus();
}
public void windowClosing( WindowEvent e ){
if (field1.getText().equals("yes")) {
if (JOptionPane.showConfirmDialog
(null,"Are you sure ?")==JOptionPane.YES_OPTION) {
setVisible(false);
dispose();
}
}
}
} );
pack();
setVisible( true );
}

public static void main(String args[]) {


new CloseOrNot();
}
}

Maximize a JFrame
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0479.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.
*/

Maximize a JFrame 911


Real's HowTo PDF version

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

Capture System.out into a JFrame


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0435.html

import java.awt.*;
import javax.swing.*;
import java.io.*;

/**
* http://tanksoftware.com/juk/developer/src/com/
* tanksoftware/util/RedirectedFrame.java
* A Java Swing class that captures output to the command line
** (eg, System.out.println)
* RedirectedFrame
* <p>
* This class was downloaded from:
* Java CodeGuru (http://codeguru.earthweb.com/java/articles/382.shtml) <br>
* The origional author was Real Gagnon ([email protected]);
* 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";

Capture System.out into a JFrame 912


Real's HowTo PDF version

private boolean catchErrors;


private boolean logFile;
private String fileName;
private int width;
private int height;
private int closeOperation;

TextArea aTextArea = new TextArea();


PrintStream aPrintStream =
new PrintStream(
new FilteredStream(
new ByteArrayOutputStream()));

/** Creates a new RedirectFrame.


* From the moment it is created,
* all System.out messages and error messages (if requested)
* are diverted to this frame and appended to the log file
* (if requested)
*
* for example:
* RedirectedFrame outputFrame =
* new RedirectedFrame
(false, false, null, 700, 600, JFrame.DO_NOTHING_ON_CLOSE);
* this will create a new RedirectedFrame that doesn't catch errors,
* nor logs to the file, with the dimentions 700x600 and it doesn't
* close this frame can be toggled to visible, hidden by a controlling
* class by(using the example) outputFrame.setVisible(true|false)
* @param catchErrors set this to true if you want the errors to
* also be caught
* @param logFile set this to true if you want the output logged
* @param fileName the name of the file it is to be logged to
* @param width the width of the frame
* @param height the height of the frame
* @param closeOperation the default close operation
* (this must be one of the WindowConstants)
*/
public RedirectedFrame
(boolean catchErrors, boolean logFile, String fileName, int width,
int height, int closeOperation) {

this.catchErrors = catchErrors;
this.logFile = logFile;
this.fileName = fileName;
this.width = width;
this.height = height;
this.closeOperation = closeOperation;

Container c = getContentPane();

setTitle("Output Frame");
setSize(width,height);
c.setLayout(new BorderLayout());
c.add("Center" , aTextArea);

Capture System.out into a JFrame 913


Real's HowTo PDF version

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

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

Capture System.out into a JFrame 914


Real's HowTo PDF version

Remove the titlebar of JInternalFrame


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0333.html

((javax.swing.plaf.basic.BasicInternalFrameUI)
myInternalFrame.getUI()).setNorthPane(null);

Have borders on a JWindow/JFrame


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0204.html

You can't have a border directly on a JWindow or JFrame. You need to put a JPanel with the desired border
using the default JWindow/JFrame LayouManager (a BorderLayout). Then the JPanel is extended giving
the impression that its borders are the JWindow one.

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

public class MyWindow{


public static void main(String s[]) {
JWindow win = new JWindow();

JPanel pan = new JPanel();


pan.setBorder(new LineBorder(Color.blue));
win.getContentPane().add(pan,"Center");

pan.setLayout(new FlowLayout());
pan.add(new JButton("Hello"));
pan.add(new JButton("World"));

win.setSize(200,200);
win.setVisible(true);
}
}

Display HTML in a JScrollPane


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0205.html

Remove the titlebar of JInternalFrame 915


Real's HowTo PDF version

The JTextPane can display simple HTML page.

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

public class TestShowPage {


public static void main(String args[]) {
JTextPane tp = new JTextPane();
JScrollPane js = new JScrollPane();
js.getViewport().add(tp);
JFrame jf = new JFrame();
jf.getContentPane().add(js);
jf.pack();
jf.setSize(400,500);
jf.setVisible(true);

try {
URL url = new URL("http://www.tactika.com/realhome/contents.html");
tp.setPage(url);
}
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"));
...

Use a JOptionPane
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0376.html

Display HTML in a JScrollPane 916


Real's HowTo PDF version

import java.awt.*;

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

public class MessageBox {

/*
These are a list of STATIC MODAL dialogs

int return codes of button pressed:

-1 - WINDOW CLOSED - the X PRESSED


0 - YES and OK
1 - NO
2 - CANCEL

(thanks to flipside for the idea)


*/

public static int yesno(String theMessage){


int result = JOptionPane.showConfirmDialog((Component)
null, theMessage, "alert", JOptionPane.YES_NO_OPTION);
return result;
}

public static int yesnocancel(String theMessage){


int result = JOptionPane.showConfirmDialog((Component)
null, theMessage, "alert", JOptionPane.YES_NO_CANCEL_OPTION);
return result;
}

public static int okcancel(String theMessage){


int result = JOptionPane.showConfirmDialog((Component)
null, theMessage, "alert", JOptionPane.OK_CANCEL_OPTION);
return result;
}

public static int ok(String theMessage){


int result = JOptionPane.showConfirmDialog((Component)
null, theMessage, "alert", JOptionPane.DEFAULT_OPTION);
return result;
}

public static void main(String args[]){


int i = MessageBox.yesno("Are your sure ?");
System.out.println("ret : " + i );
i = MessageBox.yesnocancel("Are your sure ?");
System.out.println("ret : " + i );
i = MessageBox.okcancel("Are your sure ?");
System.out.println("ret : " + i );
i = MessageBox.ok("Done.");
System.out.println("ret : " + i );
}

Use a JOptionPane 917


Real's HowTo PDF version

Localize a JOptionPane dialog


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0138.html

This example will show 2 radio buttons, one for english messages and buttons and the other one for french.
Press the button to display a localized JOptionPane according to the radio button selected.

Create 2 properties files, one for english , one for french.

[JOptionPane_en.properties]
Yes=Yes
No=No
Cancel=Cancel
SaveMsg=Do you want to save your data

[JOptionPane_fr.properties]
Yes=Oui
No=Non
Cancel=Annuler
SaveMsg=Voulez-vous sauvegarder vos donnees

Then

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

public class MessageBoxExample extends JPanel


implements ActionListener {
JButton go;
AbstractButton button;
ButtonGroup group;
Locale locale;
String msg ;

public MessageBoxExample() {
group = new ButtonGroup();

locale = Locale.US; // default value


button = new JRadioButton("English", true);
button.setActionCommand("en");
button.addActionListener(this);
group.add(button);
add(button);

button = new JRadioButton("Francais");

Localize a JOptionPane dialog 918


Real's HowTo PDF version

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

Localize a JOptionPane dialog 919


Real's HowTo PDF version

frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
}

Customize a JOptionPane dialog


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0310.html

String[] buttons = {"Yes", "Yes to all", "No", "Cancel"};

int rc = JOptionPane.showOptionDialog(null,
"Do you really want to delete this file [" + filename + "]?",
"Confirmation",
JOptionPane.WARNING_MESSAGE,
0,
null,
buttons,
buttons[2]);

if (rc==-1) {
System.out.println("Dialog closed without clicking a button.");
}
else {
System.out.println(buttons[rc] + " was clicked");
}

Localize a JFileChooser
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0299.html

Modern Swing release have now built-in ready-to-use translations for the JFileChooser. The language is
choosen based on the current Locale. So you don't have to do anything to display the JFileChooser in the
right language.

The user interface elements provided by the J2SE Runtime Environment 5.0, include Swing dialogs,
messages written by the runtime environment to the standard output and standard error streams, as well as
messages produced by the tools provided with the JRE. These user interface elements are localized into the
following languages:

Language Locale ID

Customize a JOptionPane dialog 920


Real's HowTo PDF version

Chinese (Simplified) zh_CN


Chinese (Traditional) zh_TW
English en
French fr
German de
Italian it
Japanese ja
Korean ko
Spanish es
Swedish sv
Sun Supported Locales

This example will show 2 radio buttons, one for english, one for french. Press the button to display a
localized JFileChooser according to the radio button selected.

Create 2 properties files, one for english , one for french (these files are incomplete but should be enough to
get you started).

[JFileChooser_en.properties]

Title=Real's JFileChooser
lookInLabelText=Current
filesOfTypeLabelText=File type
upFolderToolTipText=go up

[JFileChooser_fr.properties]

Title=JFileChooser de R\u00e9al
lookInLabelText=Courant
filesOfTypeLabelText=Type de fichier
upFolderToolTipText=Remonte

Then

[LocalizeJFileChooser.java]

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

public class LocalizeJFileChooser extends JPanel


implements ActionListener {
JButton go;
AbstractButton button;

Localize a JFileChooser 921


Real's HowTo PDF version

ButtonGroup group;
Locale locale;
String msg ;

protected JFileChooser z_chooser;


String z_choosertitle;

public LocalizeJFileChooser() {
group = new ButtonGroup();

locale = Locale.US; // default value


button = new JRadioButton("English", true);
button.setActionCommand("en");
button.addActionListener(this);
group.add(button);
add(button);

button = new JRadioButton("Francais");


button.setActionCommand("fr");
button.addActionListener(this);
group.add(button);
add(button);

go = new JButton("Do it");


go.addActionListener(this);
add(go);

locale = Locale.US;

public void setUILanguage() {


ResourceBundle rb;
rb = ResourceBundle.getBundle("JFileChooser", locale);

z_choosertitle = rb.getString("Title");

UIManager.put
("FileChooser.lookInLabelText",
rb.getString("lookInLabelText"));
UIManager.put
("FileChooser.filesOfTypeLabelText",
rb.getString("filesOfTypeLabelText"));
UIManager.put
("FileChooser.upFolderToolTipText",
rb.getString("upFolderToolTipText"));
/*
do the same with :
FileChooser.fileNameLabelText
FileChooser.homeFolderToolTipText
FileChooser.newFolderToolTipText
FileChooser.listViewButtonToolTipTextlist
FileChooser.detailsViewButtonToolTipText
FileChooser.saveButtonText=Save

Localize a JFileChooser 922


Real's HowTo PDF version

FileChooser.openButtonText=Open
FileChooser.cancelButtonText=Cancel
FileChooser.updateButtonText=Update
FileChooser.helpButtonText=Help
FileChooser.saveButtonToolTipText=Save
FileChooser.openButtonToolTipText=Open
FileChooser.cancelButtonToolTipText=Cancel
FileChooser.updateButtonToolTipText=Update
FileChooser.helpButtonToolTipText=Help

Almost all Swing widgets can be customize this way. You can
examine the Swing sources to get these values or check
http://www.gargoylesoftware.com/papers/plafdiff.html for
a list of them.

*/

public void actionPerformed(ActionEvent e) {


int result;

if (e.getSource() instanceof JRadioButton) {


if (e.getActionCommand().equals("en"))
locale = Locale.US;
else
locale = Locale.FRANCE;
setUILanguage();
}
else {
z_chooser = new JFileChooser();
z_chooser.setCurrentDirectory(new java.io.File("."));
z_chooser.setDialogTitle(z_choosertitle);
if (z_chooser.showOpenDialog(this) !=
JFileChooser.APPROVE_OPTION)
return;
}
}

public Dimension getPreferredSize(){


return new Dimension(200, 200);
}

public static void main(String s[]) {


JFrame frame = new JFrame("");
LocalizeJFileChooser panel = new LocalizeJFileChooser();
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
frame.getContentPane().add(panel,"Center");

Localize a JFileChooser 923


Real's HowTo PDF version

frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
}

Select a directory with a JFileChooser


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0370.html

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

public class DemoJFileChooser extends JPanel


implements ActionListener {
JButton go;

JFileChooser chooser;
String choosertitle;

public DemoJFileChooser() {
go = new JButton("Do it");
go.addActionListener(this);
add(go);
}

public void actionPerformed(ActionEvent e) {


int result;

chooser = new JFileChooser();


chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle(choosertitle);
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
//
// disable the "All files" option.
//
chooser.setAcceptAllFileFilterUsed(false);
//
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
System.out.println("getCurrentDirectory(): "
+ chooser.getCurrentDirectory());
System.out.println("getSelectedFile() : "
+ chooser.getSelectedFile());
}
else {
System.out.println("No Selection ");
}

Select a directory with a JFileChooser 924


Real's HowTo PDF version

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

Disable the JFileChooser's 'New folder' button


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0569.html

No easy way to disable the "New Folder" button. You need to iterate the JFileChooser components until the
right one and disable it.

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

public class DemoJFileChooser extends JPanel


implements ActionListener {
JButton go;

JFileChooser chooser;
String choosertitle;

public DemoJFileChooser() {
go = new JButton("Do it");
go.addActionListener(this);
add(go);
}

public void actionPerformed(ActionEvent e) {


int result;

Disable the JFileChooser's 'New folder' button 925


Real's HowTo PDF version

chooser = new JFileChooser();


chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle(choosertitle);

disableNewFolderButton(chooser);

//
int rc = chooser.showOpenDialog(this);
if (rc == JFileChooser.APPROVE_OPTION) {
System.out.println("getCurrentDirectory(): "
+ chooser.getCurrentDirectory());
System.out.println("getSelectedFile() : "
+ chooser.getSelectedFile());
}
else {
System.out.println("No Selection!");
}
}

public void disableNewFolderButton( Container c ) {


int len = c.getComponentCount();
for (int i = 0; i < len; i++) {
Component comp = c.getComponent(i);
if (comp instanceof JButton) {
JButton b = (JButton)comp;
Icon icon = b.getIcon();
if (icon != null
&& icon == UIManager.getIcon("FileChooser.newFolderIcon"))
b.setEnabled(false);
}
else if (comp instanceof Container) {
disableNewFolderButton((Container)comp);
}
}
}

public Dimension getPreferredSize(){


return new Dimension(200, 200);
}

public static void main(String s[]) {


JFrame frame = new JFrame("");
DemoJFileChooser panel = new DemoJFileChooser();
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());

Disable the JFileChooser's 'New folder' button 926


Real's HowTo PDF version

frame.setVisible(true);
}
}

Validate a filename from a JFileChooser


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0568.html

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

public class DemoJFileChooser extends JPanel


implements ActionListener {
JButton go;

JFileChooser chooser;
String choosertitle;

public DemoJFileChooser() {
go = new JButton("Do it");
go.addActionListener(this);
add(go);
}

public void actionPerformed(ActionEvent e) {


int result;

chooser = new JFileChooser();


chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle(choosertitle);
//
int rc = chooser.showOpenDialog(this);
//
// loop until a .java file is selected
//
// possible to perform complex validation
// using a regular expression with .matches(regexp)
//
while(rc == JFileChooser.APPROVE_OPTION &&
!chooser.getSelectedFile().getName().endsWith(".java")){
JOptionPane.showMessageDialog(null,
"The file " + chooser.getSelectedFile()
+ " is not java source file.", "Open Error",
JOptionPane.ERROR_MESSAGE);
rc = chooser.showOpenDialog(this);
}

Validate a filename from a JFileChooser 927


Real's HowTo PDF version

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

Make a JFrame looks like a JDialog


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0582.html

Make a JFrame unresizable and with no min/max button. The difference with JDialog is that a JFrame is
shown on the taskbar (win) while a JDialog is not.

import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;

Make a JFrame looks like a JDialog 928


Real's HowTo PDF version

public class JFrameWithNoMinMax extends JFrame {

public JFrameWithNoMinMax() {
createAndShowUI();
}

private void createAndShowUI(){


setTitle("This JFRAME looks like JDialog");
setSize(new Dimension(500,100));
setUndecorated(true);
setResizable(false);
getRootPane().setWindowDecorationStyle(JRootPane.PLAIN_DIALOG);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
//addWindowListener(new WindowAdapter(){
// public void windowClosing(WindowEvent e) {
// System.out.println("Window Closing");
// System.exit(0);
// }
//});
}

public static void main(String[] args){


SwingUtilities.invokeLater(new Runnable(){
public void run(){
new JFrameWithNoMinMax().setVisible(true);
}
});
}
}

Make a JFrame always visible


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0638.html

import javax.swing.JFrame;
import javax.swing.JLabel;

public class Test2 {


public static void main(String[] args) {
JFrame frame = new JFrame("Hello!!");

Make a JFrame always visible 929


Real's HowTo PDF version

frame.setAlwaysOnTop( true );
frame.setLocationByPlatform( true );
frame.add(new JLabel(" Always visible") );
frame.pack();
frame.setVisible(true);
}
}

Show a JFrame on a specific screen in a dual monitor


configuration
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-show-jframe-on-a-specific-screen.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);
}
}
}

Make a frame not visible in the taskbar


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-make-a-frame-not-visible-in-the-taskbar.html

Show a JFrame on a specific screen in a dual monitor configuration 930


Real's HowTo PDF version

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

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

Based on JTextField content, enable or disable a JButton


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0196.html

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

public class DemoJButtonDisabled extends JApplet {


JButton button;
JTextField textfield;
Document document;
public void init() {
getContentPane().setLayout(new FlowLayout());
textfield = new JTextField(10);

Make a frame not visible in the taskbar 931


Real's HowTo PDF version

getContentPane().add(textfield);
button = new JButton("foo");
getContentPane().add(button);
button.setEnabled(false);

document = textfield.getDocument();
document.addDocumentListener
(new JButtonStateController(button));
}
}

class JButtonStateController implements DocumentListener {


private JButton button;

JButtonStateController(JButton b) {
button = b;
}

public void changedUpdate(DocumentEvent e) {


disableIfEmpty(e);
}

public void insertUpdate(DocumentEvent e){


disableIfEmpty(e);
}

public void removeUpdate(DocumentEvent e){


disableIfEmpty(e);
}

public void disableIfEmpty(DocumentEvent e) {


button.setEnabled(e.getDocument().getLength() > 0);
}
}

Apply special filter to a JtextField


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0197.html

The following class will help a JTextField to filter numeric or alphanumeric characters.

import javax.swing.*;
import javax.swing.text.*;

public class JTextFieldFilter extends PlainDocument {


public static final String LOWERCASE =
"abcdefghijklmnopqrstuvwxyz";
public static final String UPPERCASE =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String ALPHA =

Based on JTextField content, enable or disable a JButton 932


Real's HowTo PDF version

LOWERCASE + UPPERCASE;
public static final String NUMERIC =
"0123456789";
public static final String FLOAT =
NUMERIC + ".";
public static final String ALPHA_NUMERIC =
ALPHA + NUMERIC;

protected String acceptedChars = null;


protected boolean negativeAccepted = false;

public JTextFieldFilter() {
this(ALPHA_NUMERIC);
}
public JTextFieldFilter(String acceptedchars) {
acceptedChars = acceptedchars;
}

public void setNegativeAccepted(boolean negativeaccepted) {


if (acceptedChars.equals(NUMERIC) ||
acceptedChars.equals(FLOAT) ||
acceptedChars.equals(ALPHA_NUMERIC)){
negativeAccepted = negativeaccepted;
acceptedChars += "-";
}
}

public void insertString


(int offset, String str, AttributeSet attr)
throws BadLocationException {
if (str == null) return;

if (acceptedChars.equals(UPPERCASE))
str = str.toUpperCase();
else if (acceptedChars.equals(LOWERCASE))
str = str.toLowerCase();

for (int i=0; i <str.length(); i++) {


if (acceptedChars.indexOf(str.valueOf(str.charAt(i))) == -1)
return;
}

if (acceptedChars.equals(FLOAT) ||
(acceptedChars.equals(FLOAT + "-") && negativeAccepted)) {
if (str.indexOf(".") != -1) {
if (getText(0, getLength()).indexOf(".") != -1) {
return;
}
}
}

if (negativeAccepted && str.indexOf("-") != -1) {


if (str.indexOf("-") != 0 || offset != 0 ) {
return;

Apply special filter to a JtextField 933


Real's HowTo PDF version

}
}

super.insertString(offset, str, attr);


}
}

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

public class TESTJTextFieldFilter extends JApplet{


JTextField tf1,tf1b,tf1c,tf2,tf3;
JLabel l1,l1b,l1c,l2,l3;

public void init() {


getContentPane().setLayout(new FlowLayout());
//
l1 = new JLabel("only numerics");
tf1 = new JTextField(10);
getContentPane().add(l1);
getContentPane().add(tf1);
tf1.setDocument
(new JTextFieldFilter(JTextFieldFilter.NUMERIC));

//
l1b = new JLabel("only float");
tf1b = new JTextField(10);
getContentPane().add(l1b);
getContentPane().add(tf1b);
tf1b.setDocument
(new JTextFieldFilter(JTextFieldFilter.FLOAT));

//
l1c = new JLabel("only float(can be negative)");
tf1c = new JTextField(10);
getContentPane().add(l1c);
getContentPane().add(tf1c);
JTextFieldFilter jtff = new JTextFieldFilter(JTextFieldFilter.FLOAT);
jtff.setNegativeAccepted(true);
tf1c.setDocument(jtff);

//
l2 = new JLabel("only uppercase");
tf2 = new JTextField(10);
getContentPane().add(l2);
getContentPane().add(tf2);
tf2.setDocument
(new JTextFieldFilter(JTextFieldFilter.UPPERCASE));

//
l3 = new JLabel("only 'abc123%$'");
tf3 = new JTextField(10);
getContentPane().add(l3);
getContentPane().add(tf3);

Apply special filter to a JtextField 934


Real's HowTo PDF version

tf3.setDocument
(new JTextFieldFilter("abc123%$"));
}
}

With JDK.14, you have the JFormattedTextField class. You can provide an input mask like (###)
###-#### for a telephone number, and it will not accept any input that doesn't follow that format.

import java.awt.Container;
import javax.swing.*;
import javax.swing.text.*;
import java.text.ParseException;

public class FormattedSample {


public static void main (String args[]) throws ParseException {
JFrame f = new JFrame("JFormattedTextField Sample");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container content = f.getContentPane();
content.setLayout(new BoxLayout(content, BoxLayout.PAGE_AXIS));
// canadian Social Security Number
MaskFormatter mf1 = new MaskFormatter("###-###-###");
mf1.setPlaceholderCharacter('_');
JFormattedTextField ftf1 = new JFormattedTextField(mf1);
content.add(ftf1);
// telephone number
MaskFormatter mf2 = new MaskFormatter("(###) ###-####");
JFormattedTextField ftf2 = new JFormattedTextField(mf2);
content.add(ftf2);
f.setSize(300, 100);
f.setVisible(true);
}
}

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 java.awt.Container;
import javax.swing.*;
import javax.swing.text.*;
import java.text.ParseException;

public class FormattedSample {


public static void main (String args[]) throws ParseException {
JFrame f = new JFrame("JFormattedTextField Sample");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container content = f.getContentPane();
content.setLayout(new BoxLayout(content, BoxLayout.PAGE_AXIS));

NumberFormatter nf = new NumberFormatter();


nf.setValueClass(Integer.class);
nf.setMinimum(new Integer(0));
nf.setMaximum(new Integer(100));

Apply special filter to a JtextField 935


Real's HowTo PDF version

JFormattedTextField field = new JFormattedTextField(nf);


field.setBorder(BorderFactory.createLineBorder(Color.black));
content.add(field);

f.setSize(300, 100);
f.pack();
f.setVisible(true);
}
}

Limit JTextField input to a maximum length


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0198.html

import com.sun.java.swing.text.*;

public class JTextFieldLimit extends PlainDocument {


private int limit;
// optional uppercase conversion
private boolean toUppercase = false;

JTextFieldLimit(int limit) {
super();
this.limit = limit;
}

JTextFieldLimit(int limit, boolean upper) {


super();
this.limit = limit;
toUppercase = upper;
}

public void insertString


(int offset, String str, AttributeSet attr)
throws BadLocationException {
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;

Limit JTextField input to a maximum length 936


Real's HowTo PDF version

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

Validate a value on the lostFocus event


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0199.html

The problem is when the lostFocus occurs on a Component, the gainedFocus is already sent for the next
component in the SystemEventQueue. We must grab this event, and request the focus for the previous
component (if there is a validation error). We can't use Toolkit.getDefaultToolkit().getSystemEventQueue()
directly to remove the gainedFocus event because of security restriction in Applet. This can be done with
invokeLater method of the SwingUtilities class.

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

public class DemoLostFocus extends JApplet {


JTextField tf1, tf2;
JLabel label;

public void init() {


getContentPane().setLayout(new FlowLayout());
//
label = new JLabel("must be 'a' or 'b' ");
tf1 = new JTextField(5);
getContentPane().add(label);
getContentPane().add(tf1);
tf2 = new JTextField(5);
getContentPane().add(tf2);

tf1.addFocusListener(
new FocusListener() {
public void focusGained(FocusEvent e) {};

public void focusLost(FocusEvent e) {


if (!e.isTemporary() && isEnabled() ) {
String content = tf1.getText();

Validate a value on the lostFocus event 937


Real's HowTo PDF version

if (!content.equals("a") && !content.equals("b")) {


Toolkit.getDefaultToolkit().beep();
System.out.println("illegal value! " + content );
SwingUtilities.invokeLater(new FocusGrabber(tf1));
}
}}
});
}
}

class FocusGrabber implements Runnable {


private JComponent component;

public FocusGrabber(JComponent component) {


this.component = component;
}
public void run() {
component.grabFocus();
}
}

JDK1.3 provides a new class, InputVerfier, which can be used to do that.

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

// the first JTextField expects the string "howto" as input,


// and will allow focus to change only if the required string
// is typed.

class VerifierTest extends JFrame {


public VerifierTest () {
JTextField tf,tf2;
tf = new JTextField ("howto is required");

getContentPane().add (tf, BorderLayout.NORTH);


tf.setInputVerifier(new HowtoVerifier());

tf2 = new JTextField ("howto come here");


getContentPane().add (tf2, BorderLayout.SOUTH);

addWindowListener(new WindowCloser());
}

public static void main (String [] args) {


Frame f = new VerifierTest ();
f.pack();
f.show();
}
}

Validate a value on the lostFocus event 938


Real's HowTo PDF version

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

...

Force the focus on a JTextfield when a JFrame is created


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0200.html

Force the focus on a JTextfield when a JFrame is created 939


Real's HowTo PDF version

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

Stop the beep on JFormattedTextField

Stop the beep on JFormattedTextField 940


Real's HowTo PDF version

Current version of this HowTo :


http://www.rgagnon.com/javadetails/../javadetails/java-0427.html

When the user inputs an invalid value into JFormattedTextField, the default behavior is to emit a beep. To
avoid this annoying beep, simply overload the invalidEdit() method.

class MyJFormattedTextField extends JFormattedTextField {


...
protected void invalidEdit() {}
...
}

Right justified JTextfield content


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0493.html

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

public class Test extends JApplet {


JTextField textfield;
public void init() {
getContentPane().setLayout(new FlowLayout());
textfield = new JTextField(10);
// Right-justify the text
textfield.setHorizontalAlignment(JTextField.RIGHT);
getContentPane().add(textfield);
}
}

Set the focus on a particuliar JTextField


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0510.html

SwingUtilities.invokeLater(new Runnable() {
public void run() {
myJTextField.requestFocus();
}
});

Right justified JTextfield content 941


Real's HowTo PDF version

Make JTextField unselectable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0546.html

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

class UnselectableJTextField extends JFrame {

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

Disable copy paste functionality on JTextField


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0644.html

Make JTextField unselectable 942


Real's HowTo PDF version

import java.awt.event.KeyEvent;
import java.awt.event.InputEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.JTextComponent;
import 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");
}

Disable copy paste functionality on JTextField 943


Real's HowTo PDF version

}
}
);
myFrame.setVisible(true);
}

public static void main(String args[]) {


new Test().doit();
}
}

Use a JTree to navigate in a site


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0209.html

This How-to will show you how to build a Tree (like this one) using Swing.

NOTE: This Tree Applet is different since it's plain JDK1.0.2 Applet.

First, we define the class representing a node. This node contains a title (the label), a URL, 2 icons (open
and close).

import javax.swing.*;

public class RealSwingNode extends Object {


private String _title;
private String _link;
private ImageIcon _openedIcon;
private ImageIcon _closedIcon;

RealSwingNode
(String title, String link, ImageIcon closed, ImageIcon opened) {
_title = title;
_link = link;
_openedIcon = opened;
_closedIcon = closed;
}

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

Use a JTree to navigate in a site 944


Real's HowTo PDF version

import java.awt.*;

public class RealSwingTreeIconRenderer extends Object


implements TreeCellRenderer {
JLabel _label;

RealSwingTreeIconRenderer() {
_label = new JLabel();
_label.setOpaque(true);
}

public Component getTreeCellRendererComponent


(JTree tree, Object value, boolean selected,
boolean expanded, boolean leaf, int row, boolean hasFocus) {
RealSwingNode _userObject = null;

_label.setFont(tree.getFont());

if (selected){
_label.setForeground(tree.getBackground());
_label.setBackground(tree.getForeground());
}
else {
_label.setBackground(tree.getBackground());
_label.setForeground(tree.getForeground());
}

if (value instanceof RealSwingNode) {


_userObject = (RealSwingNode) value;
}
else if(value instanceof DefaultMutableTreeNode) {
DefaultMutableTreeNode node;

node = (DefaultMutableTreeNode) value;

if (node.getUserObject() instanceof RealSwingNode) {


_userObject = (RealSwingNode) node.getUserObject();
}
}

if(_userObject != null) {
if (expanded)
_label.setIcon(_userObject.getOpenedIcon());
else
_label.setIcon(_userObject.getClosedIcon());
_label.setText(_userObject.getTitle());
}
else {
_label.setIcon(null);
_label.setText(value.toString());
}

return _label;

Use a JTree to navigate in a site 945


Real's HowTo PDF version

}
}

The next step is building the JTree in a JPanel. We use a datafile to define the Tree nodes. Since this Tree is
designed to be used in Applet, we must pass a JApplet reference to be able to read some parameters passed
via the HTML PARAM tags.

import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;
import java.net.*;
import java.io.*;

public class RealSwingTree extends JPanel


implements TreeSelectionListener {
private JApplet parentApplet;
private JTree tree;
private Font f;
private ImageIcon treeIcons[];
private String targetFrame;

public RealSwingTree() {
System.out.println(System.getProperty("os.name"));
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
}
catch (Exception ex_ignored) {
ex_ignored.printStackTrace();
}
}

public void setParentApplet(JApplet j) {


parentApplet = j;
}

public void initTree() {


// build the tree from the datafile
DefaultMutableTreeNode rootNode = null;
DefaultMutableTreeNode currentNode = null;
DefaultMutableTreeNode node = null;
RealSwingNode rsn = null;
RealSwingTreeIconRenderer rstir;
TreeSelectionModel tsm;

int token, value=0, oldvalue=0, rootvalue=0, image1idx=0, image2idx=0;


String strValue, lnkValue, imageValue;
boolean rootDone=false;
boolean itemDone=true;
System.out.println("[RealSwingTree] Begin populateTree() " );

Use a JTree to navigate in a site 946


Real's HowTo PDF version

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

Use a JTree to navigate in a site 947


Real's HowTo PDF version

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

Use a JTree to navigate in a site 948


Real's HowTo PDF version

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

Use a JTree to navigate in a site 949


Real's HowTo PDF version

}
}
}
}

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 How-to" "" "0" "1"
1 "What's new" "java-new.html" "2" "2"
1 "General" "" "0" "1"
2 "part 1" "java-g1.html" "2" "2"

Here the HTML used to test the Tree. Since there is almost no error checking, all PARAM tags are
required.

<HTML><BODY>
<APPLET CODE="RealSwingTreeApplet.class"
NAME="RealTree"
HEIGHT=2000 WIDTH=196>
<PARAM NAME="datafile" VALUE="treedata.txt">
<PARAM NAME="bgcolor" VALUE="FFFFFF">
<PARAM NAME="font" VALUE="Courier">
<PARAM NAME="point" VALUE="11">
<PARAM NAME="images" VALUE="./images">
<PARAM NAME="targetframe" VALUE="_top">
<PARAM NAME="rootimage" VALUE="root.gif">

Use a JTree to navigate in a site 950


Real's HowTo PDF version

<PARAM NAME="leaveimageslist"
VALUE="fclose.jpg,fopen.jpg,page.jpg">
</APPLET></BODY></HTML>

The <APPLET> tag and Swing applet are ok with Appletviewer, but in most browser, you need to execute
the Applet under the Java plugin. Therefore, you need to use the <EMBED> tag with Netscape or
<OBJECT> tag with IE. So for example, with Netscape, the HTML will be like this :

<HTML><BODY>
<EMBED type="application/x-java-applet;version=1.2.2" width="200"
height="2000" code="RealSwingTreeApplet.class"
datafile="treedata.txt"
bgcolor="FFFFFF"
... other params here ...

pluginspage="http://java.sun.com/products/plugin/1.2/plugin-install.html">
<NOEMBED>
No JDK 1.2 support for APPLET!!
</NOEMBED>
</EMBED>
</BODY></HTML>

Finally, you may want to grab these images used in this How-to .

root.gif fclose.jpg fopen.jpg fpage.jpg

Expand or collapse a JTree


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0210.html

import javax.swing.*;
import javax.swing.tree.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class SimpleTree extends JPanel {


JTree tree;
DefaultMutableTreeNode root, node1, node2, node3, node4;
public SimpleTree() {
root = new DefaultMutableTreeNode("root", true);
node1 = new DefaultMutableTreeNode("node 1", true);
node2 = new DefaultMutableTreeNode("node 2" , true);
node3 = new DefaultMutableTreeNode("node 3" , true);
node4 = new DefaultMutableTreeNode("node 4" , true);
root.add(node1);

Expand or collapse a JTree 951


Real's HowTo PDF version

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

Expand or collapse a JTree 952


Real's HowTo PDF version

if (ae.getSource() == b3) expandToLast(panel.tree);


if (ae.getSource() == b2) collapseAll(panel.tree);
}

public void expandAll(JTree tree) {


int row = 0;
while (row <tree.getRowCount()) {
tree.expandRow(row);
row++;
}
}

public void expandToLast(JTree tree) {


// expand to the last leaf from the root
DefaultMutableTreeNode root;
root = (DefaultMutableTreeNode) tree.getModel().getRoot();
tree.scrollPathToVisible(new TreePath(root.getLastLeaf().getPath()));
}

/*
// alternate version, suggested by C.Kaufhold
public void expandToLast(JTree tree) {
TreeModel data = tree.getModel();
Object node = data.getRoot();

if (node == null) return;

TreePath p = new TreePath(node);


while (true) {
int count = data.getChildCount(node);
if (count == 0) break;
node = data.getChild(node, count - 1);
p = p.pathByAddingChild(node);
}
tree.scrollPathToVisible(p);
}
*/

public void collapseAll(JTree tree) {


int row = tree.getRowCount() - 1;
while (row >= 0) {
tree.collapseRow(row);
row--;
}
}
}

Expand or collapse a JTree 953


Real's HowTo PDF version

Have a popup attached to a JTree


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0211.html

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import 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() );

Have a popup attached to a JTree 954


Real's HowTo PDF version

}
}
}
);

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

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

Have a popup attached to a JTree 955


Real's HowTo PDF version

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

Traverse a JTree
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0313.html

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

public class TraverseSimpleTree extends JPanel {


JTree tree;
DefaultMutableTreeNode root, n1, n2, n3,n4,n5;
public TraverseSimpleTree() {
root = new DefaultMutableTreeNode("root", true);
n1 = new DefaultMutableTreeNode("node 1", true);
n2 = new DefaultMutableTreeNode("node 2" , true);
n3 = new DefaultMutableTreeNode("node 3" , true);
n4 = new DefaultMutableTreeNode("node 4" , true);
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(){

Traverse a JTree 956


Real's HowTo PDF version

return new Dimension(200, 120);


}

public static void main(String s[]){


MyJFrame frame = new MyJFrame("Traverse Tree");
}
}

class WindowCloser extends WindowAdapter {


public void windowClosing(WindowEvent e) {
Window win = e.getWindow();
win.setVisible(false);
System.exit(0);
}
}

class MyJFrame extends JFrame implements ActionListener {


JButton b1, b2, b3;
TraverseSimpleTree panel;
MyJFrame(String s) {
super(s);
setForeground(Color.black);
setBackground(Color.lightGray);
panel = new TraverseSimpleTree();
getContentPane().add(panel,"Center");

b1 = new JButton("Traverse (check the console)");

b1.addActionListener(this);
getContentPane().add(b1,"West");
setSize(300,300);
setVisible(true);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowCloser());
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b1) traverse(panel.tree);
}

public void traverse(JTree tree) {


TreeModel model = tree.getModel();
if (model != null) {
Object root = model.getRoot();
System.out.println(root.toString());
walk(model,root);
}
else
System.out.println("Tree is empty.");
}

protected void walk(TreeModel model, Object o){


int cc;

Traverse a JTree 957


Real's HowTo PDF version

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

Dotted Lines in a JTree


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0325.html

In your code

...
tree.putClientProperty("JTree.lineStyle", "Angled");
...

Or from the command line

java -DJTree.lineStyle=Angled MyApp

Other possible values :

None
No lines are drawn anywhere on the tree.
Angled
Vertical lines between nodes at the same level,
horizontal line to child node.
Horizontal
A single horizontal line between nodes immediately
attached to the root node. This is the default setting.

See also List of undocumented properties to change the behavior of Swing in Suns JVM.

Explore directories with a JTree


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0324.html

Dotted Lines in a JTree 958


Real's HowTo PDF version

import javax.swing.*;
import javax.swing.tree.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;
import 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");
}
}

class WindowCloser extends WindowAdapter {


public void windowClosing(WindowEvent e) {
Window win = e.getWindow();
win.setVisible(false);
System.exit(0);
}
}

Explore directories with a JTree 959


Real's HowTo PDF version

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

Prevent JTree collapsing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0339.html

myJTree.addTreeWillExpandListener
(new TreeWillExpandListener() {
public void treeWillExpand(TreeExpansionEvent e) { }
public void treeWillCollapse(TreeExpansionEvent e)
throws ExpandVetoException {
throw new ExpandVetoException(e, "you can't collapse this JTree");
}
});

Single selection in a JTree


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0395.html

myJTree.getSelectionModel().
setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

Also you may want to disable the CTRL-A key which select the entire tree.

[JDK1.2]
KeyStroke ks = KeyStroke.getKeyStroke("ctrl A");
tree.unregisterKeyboardAction(ks);

[JDK1.3+]

Prevent JTree collapsing 960


Real's HowTo PDF version

KeyStroke ks = KeyStroke.getKeyStroke("ctrl A");


tree.getInputMap().put(ks, "none");

Reduce JTree children indentation


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0398.html

BasicTreeUI basicTreeUI = (BasicTreeUI) myJTree.getUI();


basicTreeUI.setRightChildIndent(10);

Use + or - for JTree Icons


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0517.html

The default look and feel for a JTree.

If you want to use the more regular - and + sign to collapse or expand a tree node.

you need to call

UIManager.put("Tree.expandedIcon", new ImageIcon("treeMinus.gif"));


UIManager.put("Tree.collapsedIcon", new ImageIcon("treePlus.gif"));

to replace default images.

Single selection in a JTree 961


Real's HowTo PDF version

Example

import javax.swing.*;
import javax.swing.tree.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class SimpleTree extends JPanel {


JTree tree;
DefaultMutableTreeNode root, node1, node2, node3, node4;
public SimpleTree() {
root = new DefaultMutableTreeNode("root", true);
node1 = new DefaultMutableTreeNode("node 1", true);
node2 = new DefaultMutableTreeNode("node 2" , true);
node3 = new DefaultMutableTreeNode("node 3" , true);
node4 = new DefaultMutableTreeNode("node 4" , true);
root.add(node1);
node1.add(node2);
root.add(node3);
node3.add(node4);
setLayout(new BorderLayout());
UIManager.put("Tree.expandedIcon",
new ImageIcon("treeMinus.gif"));
UIManager.put("Tree.collapsedIcon",
new ImageIcon("treePlus.gif"));
tree = new JTree(root);
add(new JScrollPane((JTree)tree),"Center");
}

public Dimension getPreferredSize(){


return new Dimension(200, 120);
}

public static void main(String s[]){


MyJFrame frame = new MyJFrame("SimpleTree");
}
}

class WindowCloser extends WindowAdapter {


public void windowClosing(WindowEvent e) {
Window win = e.getWindow();
win.setVisible(false);
System.exit(0);
}
}

class MyJFrame extends JFrame {


SimpleTree panel;
MyJFrame(String s) {
super(s);
setForeground(Color.black);
setBackground(Color.lightGray);
panel = new SimpleTree();

Use + or - for JTree Icons 962


Real's HowTo PDF version

getContentPane().add(panel,"Center");

setSize(300,300);
setVisible(true);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowCloser());
}
}

The required small GIFs :

Change JTable header color


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0334.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 = {
{"row1-col1", "row1-col2"},
{"row2-col1", "row2-col2"},
{"row3-col1", "row3-col2"},
{"row4-col1", "row4-col2"},
{"row5-col1", "row5-col2"}};

String[] columnNames = {"col1", "col2"};

table = new JTable(cellData, columnNames);

scrollPane = new JScrollPane( table );


topPanel.add( scrollPane, BorderLayout.CENTER );

Change JTable header color 963


Real's HowTo PDF version

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

Detect doubleclick on a JTable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0336.html

import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;

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

public class SimpleTable


implements ListSelectionListener {
JTable aTable;
public SimpleTable() {
JFrame frame = new JFrame("Table");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}});

final String[] names = {"First Name", "Last Name", "Id" };


final Object[][] data = {
{"Mark", "Andrews", new Integer(1)},
{"Tom", "Ball", new Integer(2)},
{"Alan", "Chung", new Integer(3)},
};

TableModel dataModel = new AbstractTableModel() {


public int getColumnCount() { return names.length; }
public int getRowCount() { return data.length;}
public Object getValueAt(int row, int col) {
return data[row][col];
}
public String getColumnName(int column) {return names[column];}
public Class getColumnClass(int col) {
return getValueAt(0,col).getClass();

Detect doubleclick on a JTable 964


Real's HowTo PDF version

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

Detect doubleclick on a JTable 965


Real's HowTo PDF version

Read a data file into a JTable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0213.html

The first line of the data file contains the column names. Fields are separated by the "|" character.

[customers.dat]

Id|Name|City|Phone
102|Beth Reiser|New York|(212)5558725
111|Dylan Ricci|Syracuse|(315)5554486
116|Brian Gugliuzza|Mamaroneck|(914)5553817
120|Gertrude Stein|Elmsford|(914)5553476
131|Daljit Sinnot|Bohemia|(516)5559811

First we need a TableModel to define the data structure to used by the JTable.

[DataFileTableModel.java]

import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
import java.io.*;
import java.util.*;

public class DataFileTableModel extends AbstractTableModel {


protected Vector data;
protected Vector columnNames ;
protected String datafile;

public DataFileTableModel(String f){


datafile = f;
initVectors();
}

public void initVectors() {


String aLine ;
data = new Vector();
columnNames = new Vector();
try {
FileInputStream fin = new FileInputStream(datafile);
BufferedReader br = new BufferedReader(new InputStreamReader(fin));
// extract column names
StringTokenizer st1 =
new StringTokenizer(br.readLine(), "|");
while(st1.hasMoreTokens())
columnNames.addElement(st1.nextToken());
// extract data
while ((aLine = br.readLine()) != null) {

Read a data file into a JTable 966


Real's HowTo PDF version

StringTokenizer st2 =
new StringTokenizer(aLine, "|");
while(st2.hasMoreTokens())
data.addElement(st2.nextToken());
}
br.close();
}
catch (Exception e) {
e.printStackTrace();
}
}

public int getRowCount() {


return data.size() / getColumnCount();
}

public int getColumnCount(){


return columnNames.size();
}

public String getColumnName(int columnIndex) {


String colName = "";

if (columnIndex <= getColumnCount())


colName = (String)columnNames.elementAt(columnIndex);

return colName;
}

public Class getColumnClass(int columnIndex){


return String.class;
}

public boolean isCellEditable(int rowIndex, int columnIndex) {


return false;
}

public Object getValueAt(int rowIndex, int columnIndex) {


return (String)data.elementAt
( (rowIndex * getColumnCount()) + columnIndex);
}

public void setValueAt(Object aValue, int rowIndex, int columnIndex) {


return;
}
}

[DataFileTable.java]

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.io.*;
import java.util.*;

Read a data file into a JTable 967


Real's HowTo PDF version

public class DataFileTable extends JPanel {


public DataFileTable(String dataFilePath) {
JTable table;
DataFileTableModel model;
Font f;

f = new Font("SanSerif",Font.PLAIN,24);
setFont(f);
setLayout(new BorderLayout());

model = new DataFileTableModel(dataFilePath);

table = new JTable();


table.setModel(model);
table.createDefaultColumnsFromModel();

JScrollPane scrollpane = new JScrollPane(table);


add(scrollpane);
}

public Dimension getPreferredSize(){


return new Dimension(400, 300);
}

public static void main(String s[]) {


JFrame frame = new JFrame("Data File Table");
DataFileTable panel;

panel = new DataFileTable("customers.dat");

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setForeground(Color.black);
frame.setBackground(Color.lightGray);
frame.getContentPane().add(panel,"Center");

frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
frame.addWindowListener(new WindowCloser());
}
}

class WindowCloser extends WindowAdapter {


public void windowClosing(WindowEvent e) {
Window win = e.getWindow();
win.setVisible(false);
System.exit(0);
}
}

Read a data file into a JTable 968


Real's HowTo PDF version

Disable row selection in a JTable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0338.html

aTable.setRowSelectionAllowed(false);
aTable.setColumnSelectionAllowed(false);
aTable.setCellSelectionEnabled(false);

Detect a data file modification and reload a JTable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0214.html

We use the Observer/Observable mechanism to detect if the data file have been modifed since the last time.

We use the same data file and DataFileTableModel as the previous How-to. Some minor modifications are
needed for the DataFileTable class. This class now implements the Observer interface (see the update()
method which will be called when the Observable object send a notification).

[DataFileTable.java]

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.io.*;
import java.util.*;

public class DataFileTable extends JPanel


implements Observer {
protected JTable table;
protected DataFileTableModel model;

public DataFileTable(String dataFilePath) {


DataFileWatchdog wd;
Font f;

f = new Font("SanSerif",Font.PLAIN,24);
setFont(f);
setLayout(new BorderLayout());

model = new DataFileTableModel(dataFilePath);

table = new JTable();


table.setModel(model);
table.createDefaultColumnsFromModel();

Disable row selection in a JTable 969


Real's HowTo PDF version

JScrollPane scrollpane = new JScrollPane(table);


add(scrollpane);

// this watchdog (an Observable object)


// is monitoring any file change
wd = new DataFileWatchdog(dataFilePath);
wd.addObserver(this);
}

public void update(Observable o, Object arg) {


// reload data because data file have changed
model.initVectors();
table.repaint();
}

public Dimension getPreferredSize(){


return new Dimension(400, 300);
}

public static void main(String s[]) {


JFrame frame = new JFrame("Data File Table");
DataFileTable panel;

panel = new DataFileTable("customers.dat");


frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setForeground(Color.black);
frame.setBackground(Color.lightGray);
frame.getContentPane().add(panel,"Center");

frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
frame.addWindowListener(new WindowCloser());
}
}

class WindowCloser extends WindowAdapter {


public void windowClosing(WindowEvent e) {
Window win = e.getWindow();
win.setVisible(false);
System.exit(0);
}
}

The DataFileWatchdog, an Observable object, is simple. We use a Swing Timer to check every second if a
given file have changed. If the timestamp is different then the last one, then all registered Observers are
notified about it.

[DataFileWatchdog.java]

import javax.swing.Timer;
import java.awt.event.*;
import java.io.*;

Detect a data file modification and reload a JTable 970


Real's HowTo PDF version

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

Hide a column in JTable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0216.html

To hide one column (or more) in a JTable, don't give a column name. To get back the hidden data, you
must use the TableModel.

[TableHideColumn.java]

import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;

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

public class TableHideColumn


implements ListSelectionListener {
JTable tableView;

Hide a column in JTable 971


Real's HowTo PDF version

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

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

Hide a column in JTable 972


Real's HowTo PDF version

System.out.print(value + " " );


}
System.out.println();
}
}
}

public static void main(String[] args) {


new TableHideColumn();
}
}

This technique is not the best one since a exception is generated when Swing tries to display an "hidden
column".

For a better way check out these links :

http://www.codeguru.com/java/articles/660.shtml
http://www.experts-exchange.com/Programming/Programming_Languages/Java/Q_20394392.html

Scroll a JTable to the last row


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0291.html

// in the your JTable


// jump to last row
rowCount = table.getRowCount () - 1;
showCell(rowcount, 0);

// jump to first row


showCell(0, 0);

public void showCell(int row, int column) {


Rectangle rect =
getCellRect(row, column, true);
scrollRectToVisible(rect);
clearSelection();
setRowSelectionInterval(row, row);
getModel().fireTableDataChanged(); // notify the model
}

Transfer a ResultSet to a JTable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0309.html

Scroll a JTable to the last row 973


Real's HowTo PDF version

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

Have on a JScrollPane/JTable an horizontal JScrollbar


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0397.html

JScrollPane myScrollPane;
JTable myTable;

myTable = new Jtable(x,y);


myTable.setAutoResizeMode (JTable.AUTO_RESIZE_OFF);
myScrollPane = new JScrollPane(myTable);
myScrollPane.setHorizontalScrollBar(new JScrollBar());
myTable.setAutoResizeMode (JTable.AUTO_RESIZE_OFF);

Make a JList select an item on doubleclick or the ENTER key


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0201.html

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

Transfer a ResultSet to a JTable 974


Real's HowTo PDF version

public class ActionJList extends JList {


/*
** sends ACTION_PERFORMED event for double-click
** and ENTER key
*/
ActionListener al;

public ActionJList(String[] it){


super(it);

addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
if (al == null) return;
Object ob[] = getSelectedValues();
if (ob.length > 1) return;
if (me.getClickCount() == 2) {
System.out.println("Sending ACTION_PERFORMED to ActionListener");
al.actionPerformed(new ActionEvent(this,
ActionEvent.ACTION_PERFORMED,
ob[0].toString()));
me.consume();
}
}
});

addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
if (al == null) return;
Object ob[] = getSelectedValues();
if (ob.length > 1) return;
if (ke.getKeyCode() == KeyEvent.VK_ENTER) {
System.out.println("Sending ACTION_PERFORMED to ActionListener");
al.actionPerformed(new ActionEvent(this,
ActionEvent.ACTION_PERFORMED,
ob[0].toString()));
ke.consume();
}
}
});
this.setSelectedIndex(0);
}

public void addActionListener(ActionListener al){


this.al = al;
}
}

To try it:

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

Make a JList select an item on doubleclick or the ENTER key 975


Real's HowTo PDF version

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

Make a JList like a scrolling text display


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0202.html

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

public class JListExample extends JPanel {


static MyJList mj;
public static void main(String s[]) {
JListExample ex = new JListExample();
JFrame frame = new JFrame("JList Scrolling Display");
JButton button = new JButton("Insert");

Make a JList like a scrolling text display 976


Real's HowTo PDF version

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

Have images in a JList


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0203.html

This snippet uses these 2 images

import javax.swing.*;
import java.awt.*;
import java.util.*;

public class JListWithImages extends JList {

Have images in a JList 977


Real's HowTo PDF version

public JListWithImages() {
setCellRenderer(new CustomCellRenderer());
}

public static void main(String[] args) {


JFrame frame = new JFrame();
JPanel panel = new JPanel();
Vector vector = new Vector();
panel.setForeground(Color.black);
panel.setBackground(Color.white);

// first line
JPanel jp1 = new JPanel();
jp1.add(new JLabel(new ImageIcon("gumby.gif")));
jp1.add(new JLabel("A line for Gumby"));
jp1.add(new JLabel(new ImageIcon("gumby2.gif")));

// second line
JPanel jp2 = new JPanel();
jp2.add(new JLabel(new ImageIcon("gumby.gif")));
jp2.add(new JLabel("Another line for Gumby"));
jp2.add(new JLabel(new ImageIcon("gumby2.gif")));

vector.addElement(jp1);
vector.addElement(jp2);

JListWithImages jlwi = new JListWithImages();


jlwi.setListData(vector);

panel.add(jlwi);
frame.getContentPane().add(panel);
frame.setSize(300,300);
frame.setVisible(true);
}

class CustomCellRenderer implements ListCellRenderer {


public Component getListCellRendererComponent
(JList list, Object value, int index,
boolean isSelected,boolean cellHasFocus) {
Component component = (Component)value;
component.setBackground
(isSelected ? Color.black : Color.white);
component.setForeground
(isSelected ? Color.white : Color.black);
return component;
}
}
}

The above How-to use the default layout, so each line line in the JList are centered. The version below is
showing each line left justified instead.

import javax.swing.*;

Have images in a JList 978


Real's HowTo PDF version

import javax.swing.border.*;
import java.awt.*;
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(new FlowLayout(FlowLayout.LEFT)); // NEW
jp1.add(new JLabel(new ImageIcon("gumby.gif")));
jp1.add(new JLabel("A line for Gumby"));
jp1.add(new JLabel(new ImageIcon("gumby2.gif")));

// second line
JPanel jp2 = new JPanel(new FlowLayout(FlowLayout.LEFT)); // NEW
jp2.add(new JLabel(new ImageIcon("gumby.gif")));
jp2.add(new JLabel("Another line for Gumby"));
jp2.add(new JLabel(new ImageIcon("gumby2.gif")));

vector.addElement(jp1);
vector.addElement(jp2);

JListWithImages jlwi = new JListWithImages();


jlwi.setListData(vector);
jlwi.setBorder(new LineBorder(Color.black));

panel.add(jlwi);
frame.getContentPane().add(panel);
frame.setSize(300,300);
frame.setVisible(true);
}

class CustomCellRenderer implements ListCellRenderer {


public Component getListCellRendererComponent
(JList list, Object value, int index,
boolean isSelected,boolean cellHasFocus) {
Component component = (Component)value;
component.setBackground
(isSelected ? Color.black : Color.white);
component.setForeground
(isSelected ? Color.white : Color.black);
return component;
}
}

Have images in a JList 979


Real's HowTo PDF version

Add a row and clear a JList


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0217.html

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

public class ClearJList extends JPanel


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

Add a row and clear a JList 980


Real's HowTo PDF version

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.getContentPane().add(panel,"Center");

frame.setSize(200,200);
frame.setVisible(true);
}
}

Sort a JList
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0218.html

import javax.swing.*;

import java.awt.event.*;
import java.awt.*;
import java.util.*;
import java.text.Collator;
// import java.util.Locale;

public class SortJList extends JPanel


implements ActionListener{
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();

Sort a JList 981


Real's HowTo PDF version

dlm.addElement
((Object) tf.getText());
}
else {
// sort
dlm = (DefaultListModel) list.getModel();
int numItems = dlm.getSize();
String[] a = new String[numItems];
for (int i=0;i<numItems;i++){
a[i] = (String)dlm.getElementAt(i);
}
sortArray(Collator.getInstance(),a);
// Locale loc = Locale.FRENCH;
// sortArray(Collator.getInstance(loc), (String[])a);
for (int i=0;i<numItems;i++) {
dlm.setElementAt(a[i], i);
}
}
}

public static void sortArray(Collator collator, String[] strArray) {


String tmp;
if (strArray.length == 1) return;
for (int i = 0; i < strArray.length; i++) {
for (int j = i + 1; j < strArray.length; j++) {
if( collator.compare(strArray[i], strArray[j] ) > 0 ) {
tmp = strArray[i];
strArray[i] = strArray[j];
strArray[j] = tmp;
}
}
}
}

public static void main(String s[]) {


JFrame frame = new JFrame("Sort JList");
SortJList panel = new SortJList();
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.getContentPane().add(panel,"Center");

frame.setSize(200,200);
frame.setVisible(true);
}
}

Double click on a JList


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0219.html

Double click on a JList 982


Real's HowTo PDF version

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

public class DClickJList extends JPanel {


public DClickJList() {
JList list = new JList();;
Vector data = new Vector();;
data.addElement("line 1");
data.addElement("line 2");
data.addElement("line 3");
list.setListData(data);
list.setSelectedIndex(0);
list.addMouseListener(new ActionJList(list));
add(new JScrollPane(list));
}

public Dimension getPreferredSize() {


return new Dimension(100, 100);
}

public static void main(String s[]){


JFrame frame = new JFrame("DClickJList");
DClickJList panel = new DClickJList();

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
}

class ActionJList extends MouseAdapter{


protected JList list;

public ActionJList(JList l){


list = l;
}

public void mouseClicked(MouseEvent e){


if(e.getClickCount() == 2){
int index = list.locationToIndex(e.getPoint());
ListModel dlm = list.getModel();
Object item = dlm.getElementAt(index);;
list.ensureIndexIsVisible(index);
System.out.println("Double clicked on " + item);
}
}
}

Double click on a JList 983


Real's HowTo PDF version

Have a PopUp on a JList


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0393.html

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

public class PopUpJList extends JPanel


implements ActionListener{
JButton jb1, jb2;
JPopupMenu popupMenu;
JMenuItem jmi1, jmi2;
JList list;
int i = 1;

public PopUpJList(){
Vector data;
setLayout(new BorderLayout());
list = new JList();
list.setModel(new DefaultListModel());
add(new JScrollPane(list),"Center");
add(jb1 = new JButton("Add"), "East");
add(jb2 = new JButton("Clear"), "West");
jb1.addActionListener(this);
jb2.addActionListener(this);

popupMenu = new JPopupMenu();


popupMenu.add(jmi1= new JMenuItem("Add"));
popupMenu.add(new JPopupMenu.Separator());
popupMenu.add(jmi2 = new JMenuItem("Clear"));

list.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
// if right mouse button clicked (or me.isPopupTrigger())
if (SwingUtilities.isRightMouseButton(me)
&& !list.isSelectionEmpty()
&& list.locationToIndex(me.getPoint())
== list.getSelectedIndex()) {
popupMenu.show(list, me.getX(), me.getY());
}
}
}
);

jmi1.addActionListener(this);
jmi2.addActionListener(this);

Have a PopUp on a JList 984


Real's HowTo PDF version

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

Make a JLabel selectable via the mouse


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0296.html

Simulate the "look and feel" of a JLabel with a JTextfield.

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

public class SelectableJLabel extends JPanel {


public SelectableJLabel() {
// a regular JLabel
add(new JLabel("You can't select me"));

// a look-alike JLabel
JTextField f = new JTextField("You can select me");
f.setEditable(false);
f.setBorder(null);
f.setForeground(UIManager.getColor("Label.foreground"));

Make a JLabel selectable via the mouse 985


Real's HowTo PDF version

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);
}
}

Change JLabel background color


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0304.html

The JLabel background is transparent by default, so changing the background color doesn't seem to do
anything. Do something like this :

aJLabel.setOpaque(true);
aJLabel.setBackground(myColor)

Bold/UnBold a JLabel
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0349.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

Change JLabel background color 986


Real's HowTo PDF version

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.

Multi-line JLabel
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0315.html

Swing 1.1.1 (or better) offers the possibility to use HTML tag to format the JLabel's text. But don't be to
fancy since the HTML support is minimal.

JLabel longLabel = new JLabel();


longLabel.setText("<html><body>This is a <p><b>" +
"<font size=\"+2\">a label on</font>" +
"</b><p>three lines.</body></html>");

Underline in Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0326.html

Since Swing (JDK1.2) implements simple HTML rendering for its components, it's possible to display
underlined string (on JLabel or JButton for example).

HTML tags must be in lowercase and simple.

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class UnderlineInSwing extends JFrame {


public UnderlineInSwing() {

super("Underline In Swing");
setSize(400, 300);

getContentPane().setLayout(new FlowLayout());

String htmlText =
"<html><p><font color=\"#800080\" "+
"size=\"4\" face=\"Verdana\">HTML in JLabel</font></p>"+
"<font size=\"2\"><u>"+
"underline is possible</u><br><b> and bold too</b></font>"+

Bold/UnBold a JLabel 987


Real's HowTo PDF version

"";
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();
}
}

Update a JLabel
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0392.html

myLabel.setText("Real's HowTo");
SwingUtilities.updateComponentTreeUI(myLabel);

Display a blinking JLabel


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0616.html

import java.awt.Color;
import java.awt.event.*;
import javax.swing.*;
import 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));

Underline in Swing 988


Real's HowTo PDF version

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;
}
}
}

// --- 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);

Display a blinking JLabel 989


Real's HowTo PDF version

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();
}
});
}
// ---
}

Set the cursor position in a JTextArea


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0332.html

To the top

myJTextArea.setCaretPosition(0);

To the end

myJTextArea.setCaretPosition(myJTextArea.getDocument().getLength());

Have Multi-line string in a JToolTip


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0337.html

We saw that since Swing (JDK1.2) implements simple HTML rendering for its components, it's possible to
display underlined string (on JLabel or JButton for example). The same feature is true for JToolTip.

Set the cursor position in a JTextArea 990


Real's HowTo PDF version

myComponent.setToolTipText
("<html><p>This ToolTip is</p><p>two lines</p></html>");

Change Tooltip color


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0365.html

UIManager.put("Tooltip.background", new ColorUIResource(...));

The default value is

javax.swing.plaf.ColorUIResource[R=204,G=204,B=255]

NOTE:Most Swing resources can be customize this way. Here a list of the resource names and their default values.

Change a JTooltip font


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0529.html

import javax.swing.*;
import javax.swing.plaf.*;
import java.awt.event.*;
import java.awt.*;

public class TooltipInSwing extends JFrame {


public TooltipInSwing() {
super("TooltipInSwing");
setSize(400, 300);
getContentPane().setLayout(new FlowLayout());

// 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");

Have Multi-line string in a JToolTip 991


Real's HowTo PDF version

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();
}
}

Keep a JTooltip visible


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0528.html

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class TooltipInSwing extends JFrame {


public TooltipInSwing() {
super("TooltipInSwing");
setSize(400, 300);
getContentPane().setLayout(new FlowLayout());

JButton b1 = new JButton("Simple tooltip 1");


b1.setToolTipText("simple tool tip without a dismiss delay");

// set a new dismiss delay to a really big value, default is 4 sec.


ToolTipManager.sharedInstance().setDismissDelay(Integer.MAX_VALUE);

getContentPane().add(b1);

WindowListener wndCloser = new WindowAdapter(){


public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
addWindowListener(wndCloser);
setVisible(true);
}

Change a JTooltip font 992


Real's HowTo PDF version

public static void main(String args[]){


new TooltipInSwing();
}
}

Display icon associated with an executable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0439.html

First technique

import java.io.*;
import javax.swing.*;

public class IconExtract1 {


public static void main(String[] args) throws Exception {
String s = "c:/windows/regedit.exe";
File file = new File(s);

// Get metadata and create an icon


sun.awt.shell.ShellFolder sf =
sun.awt.shell.ShellFolder.getShellFolder(file);
Icon icon = new ImageIcon(sf.getIcon(true));
System.out.println("type = " + sf.getFolderType());

// show the icon


JLabel ficon = new JLabel(s, icon, SwingConstants.LEFT);
JFrame frame = new JFrame();
frame.getContentPane().add(ficon);
frame.pack();
frame.setVisible(true);
}
}

output :

Second technique

import java.io.*;
import javax.swing.*;
import java.awt.*;
import javax.swing.filechooser.FileSystemView;

public class IconExtract2 {


public static void main(String[] args) throws Exception {
String s = "c:/windows/regedit.exe";

Keep a JTooltip visible 993


Real's HowTo PDF version

File file = new File(s);

// Get metadata and create an icon


Icon icon = FileSystemView.getFileSystemView().getSystemIcon(file);

// show the icon


JLabel ficon = new JLabel(s, icon, SwingConstants.LEFT);

JFrame frame = new JFrame();


frame.getContentPane().add(ficon);
frame.pack();
frame.setVisible(true);
}
}

output:

If you need more generic image, you use a JFileChooser and extract the image for a file or directory.

import java.io.*;
import javax.swing.*;
import java.awt.*;
import javax.swing.filechooser.*;

public class IconExtract3 {


public static void main(String[] args) throws Exception {

String s = "c:/windows/regedit.exe";
JFileChooser chooser = new JFileChooser();

File file = new File(s);


Icon icon = chooser.getIcon(file);

// show the icon


JLabel ficon = new JLabel(s, icon, SwingConstants.LEFT);

JFrame frame = new JFrame();


frame.getContentPane().add(ficon);
frame.pack();
frame.setVisible(true);
}
}

output for a directory :

output for a file :

Display icon associated with an executable 994


Real's HowTo PDF version

Have items in JMenubar at rightmost position


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0486.html

javax.swing.Box.createGlue() will create a "greedy" component: when it is added to a container it takes all
remaining horizontal and vertical space. Adding such a glue component to the menubar will cause
remaining menus/components to 'flow' to the right.

import javax.swing.*;
import java.awt.event.*;

class RightJMenuBar {
public static void main(String args[]) {
new RightJMenuBar().doit();
}

public void doit() {


JFrame frame = new JFrame("Real's HowTo");
JMenuBar menuBar = new JMenuBar();

// Create a menu
JMenu menu = new JMenu("Menu Label");
JMenuItem item = new JMenuItem("item");
menu.add(item);

menuBar.add(menu);

// shift to the right


menuBar.add(Box.createGlue());

// this button will be shifted right on the menubar


Action actionQuit = new AbstractAction("Quit") {
public void actionPerformed(ActionEvent evt) {
System.exit(0);
}
};
menuBar.add(new JButton(actionQuit));

frame.setJMenuBar(menuBar);
frame.setSize(300,300);
frame.setVisible(true);

Have items in JMenubar at rightmost position 995


Real's HowTo PDF version

}
}

Have an JButton with an Image


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0548.html

import java.awt.*;
import java.net.*;
import javax.swing.*;

public class TestJButton extends JApplet


{
JButton b1, b2, b3;

public void init() {


setLayout(new FlowLayout());
try {
b1 = new JButton("Regular",
new ImageIcon
(new URL("http://www.rgagnon.com/images/gumby.gif")));
add(b1);
// text on the center
b2 = new JButton("Special",
new ImageIcon
(new URL("http://www.rgagnon.com/images/gumby.gif")));
b2.setHorizontalTextPosition(SwingConstants.CENTER);
add(b2);
// text on the top
b3 = new JButton("Special",
new ImageIcon
(new URL("http://www.rgagnon.com/images/gumby.gif")));
b3.setVerticalTextPosition(SwingConstants.TOP);
b3.setHorizontalTextPosition(SwingConstants.CENTER);
add(b3);

}
catch (Exception e) {
e.printStackTrace();
}
}
}

How it looks :

Have an JButton with an Image 996


Real's HowTo PDF version

Trigger a click on a Button


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0468.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.*;

Trigger a click on a Button 997


Real's HowTo PDF version

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();
}
}
}

Written and compiled Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Trigger a click on a Button 998


Thread
java-thread

Pipe the output of a thread to the input of another one


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0140.html

We use the PipedOutputStream/PipedInputStream duo. When these streams are connected together what is
written in the PipedOutputStream can be read in PipedInputStream. That connection acts like a queue (FIFO).

Pipeline Thread

+----------+ +----------+
| thread A | --- > | thread B |
+----------+ +----------+
(PRODUCE) (CONSUME)

[ProduceData.java]

import java.io.*;

public abstract class ProduceData implements Runnable {


OutputStream os;

public ProduceData(OutputStream os) {


this.os = os;
Thread t = new Thread(this);
t.start();
}

public abstract boolean dataProduction();

public void run() {


while(dataProduction()) ;
}
}

[ConsumeData.java]

import java.io.*;

public abstract class ConsumeData implements Runnable {


InputStream is;

public ConsumeData(InputStream is) {

Thread 999
Real's HowTo PDF version

this.is = is;
Thread t = new Thread(this);
t.start();
}

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 {

Pipe the output of a thread to the input of another one 1000


Real's HowTo PDF version

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);
}
}
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) {}
}
}

Pipe the output of a thread to the input of other threads


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0141.html

The idea is to make the READ operation ATOMIC. Once the READING is started for one thread, it cannot be
interrupted by another one.

Pipeline Thread

+----------+ +----------+

Pipe the output of a thread to the input of other threads 1001


Real's HowTo PDF version

| thread A | ---- > | thread B |


+----------+ | +----------+
(produce) | (consume)
|
|
| +----------+
+- > | thread C |
+----------+
(CONSUME)

The ProduceData.class and ConsumeData.class are the same as the previous JAVA How-to.

[AtomicInputStream.java]

import java.io.*;

public class AtomicInputStream extends PipedInputStream {


int atom = 0;

AtomicInputStream(int atom) {
super();
this.atom = atom;
}
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) {

Pipe the output of a thread to the input of other threads 1002


Real's HowTo PDF version

try {
os.write(j, 0, 3);
}
catch (Exception e) {
e.printStackTrace();
return true;
}
}
return done;
}
}

[ReceiveProduction.java]

import java.io.*;

public class ReceiveProduction extends ConsumeData {


AtomicInputStream as;

ReceiveProduction(AtomicInputStream as) {
super(as);
this.as = as;
}

public boolean dataConsumption() {


byte [] i = new byte[3];
try {
for (;;) {
as.read(i);
System.out.println
(Thread.currentThread().getName()+": " +
i[0] + " " + i[1] + " " + i[2]);
}
}
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);

Pipe the output of a thread to the input of other threads 1003


Real's HowTo PDF version

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.

Wait the for the completion of one thread


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0142.html

public class testThread implements Runnable {


int i;
testThread(int i) {
super();
this.i = i;
}

public void run() {


for (int j=0; j < i; j++) {
System.out.println
(Thread.currentThread().getName() + " " + j);
}
System.out.println
(Thread.currentThread().getName() + " FINISHED");
}

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");
}

Wait the for the completion of one thread 1004


Real's HowTo PDF version

catch (Exception e) {
e.printStackTrace();
}
}
}

Control a thread from outside


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0143.html

public class TT extends Thread {


static final int RUN = 0;
static final int SUSPEND = 1;
static final int STOP = 2;
private int state = RUN;

public synchronized void setState(int s) {


state = s;
if (s == RUN) notify();
}

private boolean boolean checkState() {


while (state == SUSPEND) {
try {
wait();
}
catch (Exception e) {}
}
if (state == STOP)
return false;
return true;
}

public void run() {


while true {
doSomething();
if (!checkState())
break;
}
}

Create a Timer object


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0144.html

Control a thread from outside 1005


Real's HowTo PDF version

JDK 1.3 (or better) provides new classes called java.util.Timer and java.util.TimerTask.

import java.util.Timer;
import java.util.TimerTask;

public class ToDo {


Timer timer;

public ToDo ( int seconds ) {


timer = new Timer ( ) ;
timer.schedule ( new ToDoTask ( ) , seconds*1000 ) ;
}

class ToDoTask extends TimerTask {


public void run ( ) {
System.out.println ( "OK, It's time to do something!" ) ;
timer.cancel ( ) ; //Terminate the thread
}
}

public static void main ( String args [ ] ) {


System.out.println ( "Schedule something to do in 5 seconds." ) ;
new ToDo ( 5 ) ;
System.out.println ( "Waiting." ) ;
}
}

Swing also provide a Timer class. A Timer object will send an ActionEvent to the registered ActionListener.

import javax.swing.Timer;
import java.awt.event.*;
import java.util.*;

public class TimerDemo implements ActionListener {


Timer t = new Timer(1000,this);

TimerDemo() {
t.start();
}

public static void main(String args[]) {


TimerDemo td = new TimerDemo();
// create a dummy frame to keep the JVM running
// (for demonstation purpose)
java.awt.Frame dummy = new java.awt.Frame();
dummy.setVisible(true);
}

public void actionPerformed(ActionEvent e) {


if (e.getSource() == t) {

Create a Timer object 1006


Real's HowTo PDF version

System.out.println
("\007Being ticked " + Calendar.getInstance().getTime());
}
}
}

Pause the execution


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0145.html

public class Wait {


public static void oneSec() {
try {
Thread.currentThread().sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void manySec(long s) {
try {
Thread.currentThread().sleep(s * 1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public class TestWait {


public static void main(String args[]) {
System.out.println("Wait one second");
Wait.oneSec();
System.out.println("Done\nWait five seconds");
Wait.manySec(5);
System.out.println("Done");
}
}

Execute a method at regular interval


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0146.html

In the following example, we are using a special class, DelayedMethod, which extends the Thread class. This
Thread will receive a pointer to the "parent class" in its constructor. This pointer will be used to call a know

Pause the execution 1007


Real's HowTo PDF version

method at a specified interval.

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;

public class AnnoyingPopUps extends Applet implements


ActionListener {
Button b1, b2;
DelayedMethod dm;
int x = 0;

public void init() {


b1 = new Button("Start Annoying Popops");
b2 = new Button("Stop Annoying Popops");
add(b1); add(b2);
b1.addActionListener(this);b2.addActionListener(this);
dm = new DelayedMethod(this, 1000); // 1 second
dm.start();
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b1) {
dm.oktorun = true;
}
else if(ae.getSource() == b2) {
dm.oktorun = false;
}s
}

public void displayPopup() {


SimplePopUp d = new SimplePopUp();
d.show();
d.setLocation(x , x);
x = x + 5;
}

class SimplePopUp extends Dialog {


SimplePopUp() {
super(new Frame(), "annoying popup");
this.addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
e.getWindow().dispose();
}
}
);
}
}

class DelayedMethod extends Thread {


AnnoyingPopUps myObj = null; // customize for your need
boolean oktorun = false;

Execute a method at regular interval 1008


Real's HowTo PDF version

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 How-to to achieve to same goal by using the Timer object.

Execute a process at regular interval


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0595.html

JDK1.3 introduces a way to execute a process at regular interval (java.util.Timer and java.util.TimerTask).

JDK1.5 provides a mechanism to create a pool a scheduled task


(java.util.concurrent.ScheduledThreadPoolExecutor (javadoc)).

import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class DemoScheduledTask {

public static void main(String args[]) {

// pool size == 5
ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(5);
SimpleTask01 st01 = new SimpleTask01();
// start right now and after every 5 sec.

Execute a process at regular interval 1009


Real's HowTo PDF version

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.");
}
}
}
}

Handle concurrent read/write


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0373.html

Take the following program

import java.util.*;

public class RW {
private static Vector data = new Vector();

public static void main(String[] args) throws Exception {


new Producer().start();
new Consumer().start();
}

static class Consumer extends Thread {


Consumer(){
super("Consumer");
}
public void run(){
for(;;){
try {
Thread.sleep(1);

Handle concurrent read/write 1010


Real's HowTo PDF version

}
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");
}

Handle concurrent read/write 1011


Real's HowTo PDF version

public void run(){


for(;;){
try {
Thread.sleep(1);
}
catch (Exception e){
e.printStackTrace();
}
synchronized(data){
Iterator it = data.iterator();
while (it.hasNext()) it.next();
}
}
}
}

static class Producer extends Thread {


Producer(){
super("Producer");
}
public void run(){
for(;;){
try {
Thread.sleep(1);
}
catch (Exception e){
e.printStackTrace();
}
data.addElement(new Object());
if (data.size() > 1000) data.removeAllElements();
}
}
}
}

Communicate between threads using a Queue


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0555.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 multi-threaded world.

A Producer opens a file and puts the data into BlockingQueue.

mport java.io.*;
import java.util.concurrent.*;

Communicate between threads using a Queue 1012


Real's HowTo PDF version

public class PrepareProduction implements Runnable{


private final BlockingQueue<String> queue;

PrepareProduction(BlockingQueue<String> q) { queue = q; }

public void run() {


String thisLine;
System.out.println("Start PrepareProduction");
try {
FileInputStream fin = new FileInputStream("d:/input_data.dat");
BufferedReader input = new BufferedReader
(new InputStreamReader(fin));
while ((thisLine = input.readLine()) != null) {
queue.put(thisLine);
}
fin.close();
input.close();
// special marker for the consumer threads
// to mark the EOF
queue.put("*");
queue.put("*");
queue.put("*");
queue.put("*");
queue.put("*");
queue.put("*");
queue.put("*");
queue.put("*");
queue.put("*");
}
catch (Exception e) {
e.printStackTrace();
}
}
}

A Consumer extract a value from the Queue and execute an operation. If there is no data in the Queue, the
BlockingQueue will wait. The end-of-data is marked by the presence of a special marker (the "*" in this
example).

import java.util.concurrent.BlockingQueue;

public class DoProduction implements Runnable {


private final BlockingQueue<String> queue;

DoProduction(BlockingQueue<String> q) { queue = q; }

public void run() {


try {
System.out.println
("Start " + Thread.currentThread().getName());

String value = queue.take();


while (!value.equals("*")) {

Communicate between threads using a Queue 1013


Real's HowTo PDF version

//System.out.println
// (Thread.currentThread().getName()+": " + value );
/*
do something with value
*/
value = queue.take();
}
}
catch (Exception e) {
System.out.println
(Thread.currentThread().getName() + " " + e.getMessage());
}
}
}

A test class

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Test {


public static void main(String[] args) throws Exception {

BlockingQueue<String> q =
new LinkedBlockingQueue<String>();

Thread p1 = new Thread(new PrepareProduction(q));


Thread c1 = new Thread(new DoProduction(q));
Thread c2 = new Thread(new DoProduction(q));
Thread c3 = new Thread(new DoProduction(q));
Thread c4 = new Thread(new DoProduction(q));
Thread c5 = new Thread(new DoProduction(q));
Thread c6 = new Thread(new DoProduction(q));
Thread c7 = new Thread(new DoProduction(q));
Thread c8 = new Thread(new DoProduction(q));
Thread c9 = new Thread(new DoProduction(q));

p1.start();
c1.start();
c2.start();
c3.start();
c4.start();
c5.start();
c6.start();
c7.start();
c8.start();
c9.start();

p1.join();
c1.join();
c2.join();
c3.join();
c4.join();
c5.join();

Communicate between threads using a Queue 1014


Real's HowTo PDF version

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 multi-threaded
world, it's safer to use the synchronized version of the LinkedList implementation. Keep in mind that theses
examples are minimal and need more error checking!

First the Producer

import java.io.*;
import java.util.*;

public class PrepareProduction implements Runnable{


private final List<String> queue;

PrepareProduction(List<String> q) { queue = q; }

public void run() {


String thisLine;
System.out.println("Start PrepareProduction");
try {
FileInputStream fin = new FileInputStream("d:/input_data.dat");
BufferedReader input = new BufferedReader
(new InputStreamReader(fin));
while ((thisLine = input.readLine()) != null) {
queue.add(thisLine);
}
fin.close();
input.close();
// special marker for EOF
queue.add("*");
queue.add("*");
queue.add("*");
queue.add("*");
queue.add("*");
queue.add("*");
queue.add("*");
queue.add("*");
queue.add("*");
}
catch (Exception e) {
e.printStackTrace();
}
}
}

Communicate between threads using a Queue 1015


Real's HowTo PDF version

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()
+ " " + e.getMessage());
}
}
}

The test

import java.util.*;

public class Test {


public static void main(String[] args) throws Exception {

List q = Collections.synchronizedList
(new LinkedList<String>());

Thread p1 = new Thread(new PrepareProduction(q));


Thread c1 = new Thread(new DoProduction(q));
Thread c2 = new Thread(new DoProduction(q));
Thread c3 = new Thread(new DoProduction(q));
Thread c4 = new Thread(new DoProduction(q));
Thread c5 = new Thread(new DoProduction(q));
Thread c6 = new Thread(new DoProduction(q));
Thread c7 = new Thread(new DoProduction(q));
Thread c8 = new Thread(new DoProduction(q));
Thread c9 = new Thread(new DoProduction(q));

Communicate between threads using a Queue 1016


Real's HowTo PDF version

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.");
}
}

Get a unique identifier


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0518.html

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]

Get a unique identifier 1017


Real's HowTo PDF version

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

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 : dedc3f57-6ce1-4504-a92f-640d8d9d23c9
}
}

This is probably the preferred method.

Mini-FAQ on the subject : http://www.asciiarmor.com/post/33736615/java-util-uuid-mini-faq

Using Apache commons

If you need compatibility with 1.4 then the org.apache.commons.id.uuid is an option.

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();

public static long nextId() {


return nextId.getAndIncrement();
}
}

See also this HowTo for unique numerical id based on the system time.

Get a unique identifier 1018


Real's HowTo PDF version

Written and compiled Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Get a unique identifier 1019


Varia
java-varia

Use System time to generate unique ID


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0385.html

Since the granulaty of a PC can be as high as 55ms (down to 10ms), you can't use the System time to generate
a unique ID because of the risk of getting duplicated IDs. This can be solved by using the following technique
to make sure that the number returned is unique (in a single JVM).

public class UniqueID {


static long current= System.currentTimeMillis();
static public synchronized long get(){
return current++;
}
}

See also this HowTo

Get a unique identifier


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0518.html

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 :

Varia 1020
Real's HowTo PDF version

[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

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 : dedc3f57-6ce1-4504-a92f-640d8d9d23c9
}
}

This is probably the preferred method.

Mini-FAQ on the subject : http://www.asciiarmor.com/post/33736615/java-util-uuid-mini-faq

Using Apache commons

If you need compatibility with 1.4 then the org.apache.commons.id.uuid is an option.

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();

public static long nextId() {

Get a unique identifier 1021


Real's HowTo PDF version

return nextId.getAndIncrement();
}
}

See also this HowTo for unique numerical id based on the system time.

Get the hard disk serial number or Motherboard Serial number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0580.html

When you need to know hardware details, Java is not the best tool unless you call a JNI routine or an external
utility. The JNI solution is always the best because it is designed to interact closely with Java but it may be
more complex to develop. If your need is simple (no interaction) and the need to be cross plateform is not
present then calling an external utility is maybe "a good enough" choice.

In these 2 examples, we create the appropriate VBS script file on-the-fly and capture its output. They are very
Windows oriented since they rely on the "Windows Script Host" to execute the generated scripts.

The vbscript queries a WMI class to get a specific hardware information. Here we are using the
Win32_BaseBoard but they are many others, see http://msdn2.microsoft.com/en-us/library/aa389273.aspx for
complete list.

Motherboard serial number

import java.io.File;
import java.io.FileWriter;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class MiscUtils {


private MiscUtils() { }

public static String getMotherboardSN() {


String result = "";
try {
File file = File.createTempFile("realhowto",".vbs");
file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);

String vbs =
"Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
+ "Set colItems = objWMIService.ExecQuery _ \n"
+ " (\"Select * from Win32_BaseBoard\") \n"
+ "For Each objItem in colItems \n"
+ " Wscript.Echo objItem.SerialNumber \n"
+ " exit for ' do the first cpu only! \n"
+ "Next \n";

Get the hard disk serial number or Motherboard Serial number 1022
Real's HowTo PDF version

fw.write(vbs);
fw.close();
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
BufferedReader input =
new BufferedReader
(new InputStreamReader(p.getInputStream()));
String line;
while ((line = input.readLine()) != null) {
result += line;
}
input.close();
}
catch(Exception e){
e.printStackTrace();
}
return result.trim();
}

public static void main(String[] args){


String cpuId = MiscUtils.getMotherboardSN();
javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, cpuId, "Motherboard serial number",
javax.swing.JOptionPane.DEFAULT_OPTION);
}
}

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 low-level 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 java.io.File;
import java.io.FileWriter;
import java.io.BufferedReader;
import 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"

Get the hard disk serial number or Motherboard Serial number 1023
Real's HowTo PDF version

+"Wscript.Echo objDrive.SerialNumber"; // see note


fw.write(vbs);
fw.close();
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
BufferedReader input =
new BufferedReader
(new InputStreamReader(p.getInputStream()));
String line;
while ((line = input.readLine()) != null) {
result += line;
}
input.close();
}
catch(Exception e){
e.printStackTrace();
}
return result.trim();
}

public static void main(String[] args){


String sn = DiskUtils.getSerialNumber("C");
javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, sn, "Serial Number of C:",
javax.swing.JOptionPane.DEFAULT_OPTION);
}
}

NOTE : Other properties : objDrive.AvailableSpace/DriveType/FileSystem/IsReady

Sort an array 1
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0008.html

JDK1.4+

case-sensitive

String[] myArray = new String[] {"foo","bar","baz"};


java.util.Arrays.sort(myArray);

case-insensitive

String[] myArray = new String[] {"foo","Bar","baz"};


java.util.Arrays.sort(myArray, java.text.Collator.getInstance());

Sort an array 1 1024


Real's HowTo PDF version

less than JDK1.4

[ArraySorter.java]

public class ArraySorter {


/*
** Sort in the same array
*/
public static void sort(Object[] a, Comparer comparer) {
sort(a, null, 0, a.length - 1, true, comparer);
}

/*
** Sort a and b, using a as the reference
*/
public static void sort(Object[] a, Object[] b,
int from, int to, boolean ascending, Comparer comparer) {
// No sort
if (a == null || a.length < 2) return;

// sort using Quicksort


int i = from, j = to;
Object center = a[ (from + to) / 2 ];
do {
if (ascending) {
while( (i < to) && (comparer.compare( center, a[i]) > 0) )
i++;
while( (j > from) && (comparer.compare(center, a[j]) < 0) )
j--;
}
else {
// Decending sort
while( (i < to) && (comparer.compare( center, a[i]) < 0) )
i++;
while( (j > from) && (comparer.compare(center, a[j]) > 0) )
j--;
}
if (i < j) {
// Swap elements
Object temp = a[i]; a[i] = a[j]; a[j] = temp;
// Swap in b array if needed
if (b != null) {
temp = b[i]; b[i] = b[j]; b[j] = temp;
}
}
if (i <= j) { i++; j--; }
} while(i <= j);
// Sort the rest
if (from < j) sort(a, b, from, j, ascending, comparer);
if (i < to) sort(a, b, i, to, ascending, comparer);
}

public static interface Comparer {


/**

Sort an array 1 1025


Real's HowTo PDF version

* 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);
}
}
}

Sort an array 2
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0343.html

Sort utilities are now part of latest JDK versions.

Case sensitive

java.util.Arrays.sort(myArray);

Case insensitive

java.util.Arrays.sort(myArray, String.CASE_INSENSITIVE_ORDER);

Sort with international characters.

Sort an array 2 1026


Real's HowTo PDF version

Take the following example :

import java.util.*;
import java.io.*;

public class TestSort1 {

static String [] words = { "Réal", "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;
}
else {
return System.console().writer();
}
}
}

The output is :

Before :
Réal Real Raoul Rico
After :

Sort an array 2 1027


Real's HowTo PDF version

Raoul Real Rico Réal

which is wrong since we expect to find "Réal" after "Real".

To solve the problem , replace

java.util.Arrays.sort(words);

by

java.util.Arrays.sort(words, java.text.Collator.getInstance(java.util.Locale.FRENCH));
// or
// java.util.Arrays.sort(words, java.text.Collator.getInstance());

and the output will be :

Before :
Réal Real Raoul Rico
After :
Raoul Real Réal Rico

Or you can do it the long way :

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

Sort an array 2 1028


Real's HowTo PDF version

Do a selection sort
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0009.html

public class SelectionSort {


public static void sort(int array[]) {
sort(array, 0, array.length - 1);
}

public static void sort(int array[], int min, int max) {


if (min == max)
return;

// Find the smallest.


int index = select(array, min, max);

// Swap the smallest with the first.


int temp = array[min];
array[min] = array[index];
array[index] = temp;

// Sort the rest.


sort(array, min + 1, max);
}

private static int select(int array[], int min, int max) {


int index = min;
for (int i = min + 1; i <= max; ++i)
if (array[i] < array[index])
index = i;
return index;
}
}

Validate a Social Security Number (canadian)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0033.html

import java.util.*;
import java.io.*;

public class SSNUtils {


/**
* Validate a SSN number nnn nnn nnn

Do a selection sort 1029


Real's HowTo PDF version

*/
public static boolean validSSN(String ssn) {
if (isNumber(ssn)) {
try {
int checksum = 0;
int j = ssn.length();
int [] digit = new int[j];
for (int i=0; i < ssn.length(); i++)
digit[i] = Integer.valueOf("" + ssn.charAt(i)).intValue();
// Add odd digits except the last one
int total_odd = 0;
for (int i=0; i < digit.length-1; i+=2)
checksum += digit[i];
// Multiply by 2 even digits,
// if result > 9 then div and mod by 10,
// add the results to the checksum
// else
// add result to the checksum
int k = 0;
for (int i=0; i < digit.length; i+= 2) {
if (i < digit.length-1) {
k = digit[i+1] * 2;
if (k>9) k = (k-10) + 1;
// total_even += k;
checksum += k;
}
}

// perform a modulo 10 on the total_odd_even


// then add the last digit
int mod = checksum % 10;
checksum = digit[digit.length-1] + mod;

// if the checksum is divisible by 10 then it's valid


return ((checksum % 10) == 0);
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}
else {
return false;
}
}

/**
* Check if number is valid
*/
public static boolean isNumber(String n) {
try {
double d = Double.valueOf(n).doubleValue();
return true;
}

Validate a Social Security Number (canadian) 1030


Real's HowTo PDF version

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."));
}
}

Validate a Credit Card Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0034.html

import java.util.*;
import java.io.*;

public class CCUtils {


public static final int INVALID = -1;
public static final int VISA = 0;
public static final int MASTERCARD = 1;
public static final int AMERICAN_EXPRESS = 2;
public static final int EN_ROUTE = 3;
public static final int DINERS_CLUB = 4;

private static final String [] cardNames =


{ "Visa" ,
"Mastercard",
"American Express",
"En Route",
"Diner's CLub/Carte Blanche",

Validate a Credit Card Number 1031


Real's HowTo PDF version

};

/**
* Valid a Credit Card number
*/
public static boolean validCC(String number)
throws Exception {
int CardID;
if ( (CardID = getCardID(number)) != -1)
return validCCNumber(number);
return false;
}

/**
* Get the Card type
* returns the credit card type
* INVALID = -1;
* VISA = 0;
* MASTERCARD = 1;
* AMERICAN_EXPRESS = 2;
* EN_ROUTE = 3;
* DINERS_CLUB = 4;
*/
public static int getCardID(String number) {
int valid = INVALID;

String digit1 = number.substring(0,1);


String digit2 = number.substring(0,2);
String digit3 = number.substring(0,3);
String digit4 = number.substring(0,4);

if (isNumber(number)) {
/* ----
** VISA prefix=4
** ---- length=13 or 16 (can be 15 too!?! maybe)
*/
if (digit1.equals("4")) {
if (number.length() == 13 || number.length() == 16)
valid = VISA;
}
/* ----------
** MASTERCARD prefix= 51 ... 55
** ---------- length= 16
*/
else if (digit2.compareTo("51")>=0 && digit2.compareTo("55")<=0) {
if (number.length() == 16)
valid = MASTERCARD;
}
/* ----
** AMEX prefix=34 or 37
** ---- length=15
*/
else if (digit2.equals("34") || digit2.equals("37")) {
if (number.length() == 15)

Validate a Credit Card Number 1032


Real's HowTo PDF version

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;
}
/* -----
** 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);

Validate a Credit Card Number 1033


Real's HowTo PDF version

int checksum = 0;

for (int i=s1.length-1; i >= 0; i-= 2) {


int k = 0;

if (i > 0) {
k = Integer.valueOf(s1[i-1]).intValue() * 2;
if (k > 9) {
String s = "" + k;
k = Integer.valueOf(s.substring(0,1)).intValue() +
Integer.valueOf(s.substring(1)).intValue();
}
checksum += Integer.valueOf(s1[i]).intValue() + k;
}
else
checksum += Integer.valueOf(s1[0]).intValue();
}
return ((checksum % 10) == 0);
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}

/*
** For testing purpose
**
** java CCUtils [credit card number] or java CCUtils
**
*/
public static void main(String args[]) throws Exception {
String aCard = "";

if (args.length > 0)
aCard = args[0];
else {
BufferedReader input =
new BufferedReader(new InputStreamReader(System.in));
System.out.print("Card number : ");
aCard = input.readLine();
}
if (getCardID(aCard) > -1) {
System.out.println("This card is supported.");
System.out.println("This a " + getCardName(getCardID(aCard)));
System.out.println
("The card number " + aCard + " is "
+ (validCC(aCard)?" good.":" bad."));
}
else
System.out.println("This card is invalid or unsupported!");
}
}

Validate a Credit Card Number 1034


Real's HowTo PDF version

Obtain from where a Class is loaded


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0300.html

This HowTo detects where the class is coming from.

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

C:/temp>java LoadingFromWhere
LoadingFromWhere is loaded from file:/C:/temp/
MyClass is loaded from file:/C:/temp/

If running from a Jar

C:/temp>java -jar testing.jar


LoadingFromWhere is loaded from file:/C:/temp/testing.jar
MyClass is loaded from file:/C:/temp/testing.jar

Other technique

package com.rgagnon;

public class FromWhere {


public static void main(String args[]){
Class theClass = FromWhere.class;
java.net.URL u = theClass.getResource("");

Obtain from where a Class is loaded 1035


Real's HowTo PDF version

System.out.println("This class (FromWhere) is located at : " + u);


}
}

This technique returns the package too, If the class is in the com.rgagnon package then the output is

C:/temp> java FromWhere


This class (FromWhere) is located at : file:/C:/temp/com/rgagnon

It doesn't work if running from a Jar, a null value is returned.

See these related HowTo's :


• Get the "root" of an application
• Determine if running from JAR

Get the class name with or without the package


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0389.html

public class ClassUtils {


// returns the class (without the package if any)
public static String getClassName(Class c) {
String FQClassName = c.getName();
int firstChar;
firstChar = FQClassName.lastIndexOf ('.') + 1;
if ( firstChar > 0 ) {
FQClassName = FQClassName.substring ( firstChar );
}
return FQClassName;
}

// returns package and class name


public static String getFullClassName(Class c) {
return c.getName();
}

// returns the package without the classname, empty string if


// there is no package
public static String getPackageName(Class c) {
String fullyQualifiedName = c.getName();
int lastDot = fullyQualifiedName.lastIndexOf ('.');
if (lastDot==-1){ return ""; }
return fullyQualifiedName.substring (0, lastDot);
}

public static void main(String[] args) {

Get the class name with or without the package 1036


Real's HowTo PDF version

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

See the generated bytecode


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0495.html

Use the javap included in the JDK bin directory. javap is class disassembler, the result is similar to the
assembly code but for the JVM.

Consider the following class

class Test1 {
public static void main(String args[]) {

See the generated bytecode 1037


Real's HowTo PDF version

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[]) {
int i = 1;
new Integer(i++);
new Integer(i++);
new Integer(i++);
}
}

See the generated bytecode 1038


Real's HowTo PDF version

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

See the generated bytecode 1039


Real's HowTo PDF version

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: invokespecial #3; //Method java/lang/Integer."":(I)V
22: pop
23: iload_1
24: iconst_1
25: iadd
26: istore_1
27: new #2; //class java/lang/Integer
30: dup
31: iload_1
32: invokespecial #3; //Method java/lang/Integer."":(I)V
35: pop
36: return
}

"i=i+1" takes 2 op-codes more than the equivalent "i++".

Note this is very low-level optimization, the gain in performance is not very significative, the class is little
bit smaller.

Remember Premature optimization is the root of all evil

Self-replicating programs
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0344.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=;"+

Self-replicating programs 1040


Real's HowTo PDF version

"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

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

A curiosity
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0356.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.

A curiosity 1041
Real's HowTo PDF version

The next one is strange. From the main(), we create a Foo instance, then we call getFoo() which returns a
null and from "null" , we can access the value of fubar!
public class Foo {
static int fubar = 42;

Foo getFoo() {
return null;
}

public static void main(String args[]) {


Foo foo = new Foo();
System.out.println(foo.getFoo().fubar);
}
}
// output : 42

(from Usenet)

> I am new to java, and I really havent had time to do much work in it.
> However, I have a small project that is due next week for my class. Can
> anyone help me by providing some code? It should do the following;
>
> The program is simple. It should allow a user to input a string of digits,
> and then output the sum of those digits.
>
> For example; the user inputs 3563
> the program would then output 17 (3+5+6+3)

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!

-------------------------+ #include /* BC ok , Apollo NFG */


Real Gagnon, | int main(void) { int i=0;
Universite de Montreal | while(putchar(i++["\13Dl~fxym789\26xd"]-i));
[email protected] | while(putchar((--i)["\0\t+*)('&%$#\"\1"]+i));}

A curiosity 1042
Real's HowTo PDF version

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.

From SO

Prints hello world

for (long l = 4946144450195624l; l > 0; l >>= 5)


System.out.print((char) (((l & 31 | 64) % 95) + 32));

See also this HowTo

Common Bugs
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0361.html

Here some common mistakes :

1:

int x = 0;

for( x=0; x<10; x++ );{


System.out.println("Print only once, why not 10 times ?");
}

2:

int i = 0;

if (i = 0){
System.out.println("Won't print, why ?");
}

3:

public class WontCompile {


public static void main(String[] args) {
getInt(09);

Common Bugs 1043


Real's HowTo PDF version

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;}

Number of the beast! :-)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0477.html

public class Gates {


static String beast = "BillGates";

public static void main(String args[]) {


char [] temp = beast.toUpperCase().toCharArray();
int j = temp.length;
int i = 0;
int k = 0;
while (i < j) {
k += temp[i++];
System.out.println(temp[i-1]);
}
// Since it's really "Bill Gates III"
System.out.println(k + 1 + 1 + 1);
// output : 666 :-)
}
}

Use Java scripting engine (JDK 1.6)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0629.html

import java.util.List;
import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;

Number of the beast! :-) 1044


Real's HowTo PDF version

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
*/

// 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

Pass or retrieve values from a scripting engine (JDK 1.6)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0640.html

Use Java scripting engine (JDK 1.6) 1045


Real's HowTo PDF version

These examples use the Rhino Javascript engine bundled with Java 6.

The documentation is at Mozilla Rhino site.

import java.util.Arrays;
import java.util.List;
import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
import 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) {"
+ " 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);
}
}
}
/*

Pass or retrieve values from a scripting engine (JDK 1.6) 1046


Real's HowTo PDF version

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;
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);

Pass or retrieve values from a scripting engine (JDK 1.6) 1047


Real's HowTo PDF version

}
}
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
*/

Preventing multiple instances of an application


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0288.html

Because each application is running in it's own JVM, there is no obvious way to detect if a particuliar
application is already running.

The socket technique


One way to detect to prevent multiple application execution is to use a simple socket server. The
application will try a connection to that Server, if it's a success then the application is already running (and
the application is stopped), if no connection is made then the application create the Server.

In this example, the simple server is running on the same machine as the application so the machine name is
"localhost", the port 80 is used, you may want to customize the port number for your machine.

[JustOneServer.java]

import java.io.*;

Preventing multiple instances of an application 1048


Real's HowTo PDF version

import java.net.*;

public class JustOneServer extends Thread {


// you may need to customize this for your machine
public static final int PORT = 80 ;

ServerSocket serverSocket = null;


Socket clientSocket = null;

public void run() {


try {
// Create the server socket
serverSocket = new ServerSocket(port, 1);
while (true) {
// Wait for a connection
clientSocket = serverSocket.accept();
// System.out.println("*** Got a connection! ");
clientSocket.close();
}
}
catch (IOException ioe) {
System.out.println("Error in JustOneServer: " + ioe);
}
}
}

[JustOne.java]

import java.io.*;
import java.net.*;

public class JustOne {


SimpleDummyServer sds = null;

public static void main(String args[]){


new JustOne().doit();
}

public void doit() {


try {
Socket clientSocket = new Socket("localhost", JustOneServer.PORT);
System.out.println("*** Already running!");
System.exit(1);
}
catch (Exception e) {
sds = new JustOneServer();
sds.start();
}

while(true) {
try { System.out.print("."); Thread.sleep(5 * 60); }
catch(Exception e) { e.printStackTrace(); }
}

Preventing multiple instances of an application 1049


Real's HowTo PDF version

}
}

To test it out, open 2 consoles.

In console 1 , type java JustOne.

In console 2, type java JustOne and the application should response "Already running!".

The file lock technique


[JDK1.4+] You can use a flag file with a lock mechanism. The idea is to create and lock a file on user.home
folder with a provided name. A concurrent execution will try to lock the same file and will failed. A special
"shutdown hook" is provided to unlock the file when the JVM is shutting down.

[JustOneLock.java]

import java.io.*;
import java.nio.channels.*;

public class JustOneLock {


private String appName;
private File file;
private FileChannel channel;
private FileLock lock;

public JustOneLock(String appName) {


this.appName = appName;
}

public boolean isAppActive() {


try {
file = new File
(System.getProperty("user.home"), appName + ".tmp");
channel = new RandomAccessFile(file, "rw").getChannel();

try {
lock = channel.tryLock();
}
catch (OverlappingFileLockException e) {
// already locked
closeLock();
return true;
}

if (lock == null) {
closeLock();
return true;
}

Runtime.getRuntime().addShutdownHook(new Thread() {
// destroy the lock when the JVM is closing
public void run() {

Preventing multiple instances of an application 1050


Real's HowTo PDF version

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) { }
}
}
}

Preventing multiple instances of an application 1051


Real's HowTo PDF version

Trap JVM shutdown


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0459.html

The Java virtual machine shuts down in response to two kinds of events:

• The program exits normally, when the last non-daemon thread exits or when the exit (equivalently,
System.exit) method is invoked.
• The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a
system-wide event, such as user logoff or system shutdown.

JDK1.3

public class TrapBreak {

public static void main(String args[]) throws Exception{


new TrapBreak().doit();
}

public void doit() throws Exception{


Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("*** END ***");
}
});

while(true) { Thread.sleep(100); System.out.print("."); }


}
}

To test it out on Windows, in DOS window, start the class with

C:\temp> java TrapBreak >out.log

Now close the DOS window by clicking on the upper-right X.

Now check the out.log file, you will find "*** END ***" written by our ShutdownHook.

..................*** END ***

Minimize all programs on Windows to show the Desktop


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0637.html

Trap JVM shutdown 1052


Real's HowTo PDF version

public class Test2 {


public static void main(String args[]) throws Exception{
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.

Display a progress indicator in the console


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0666.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++);

Minimize all programs on Windows to show the Desktop 1053


Real's HowTo PDF version

fw.close();
}
pb2.showProgress = false;
System.out.println("\nDone " + j);
}
}

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 Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Display a progress indicator in the console 1054


XML
java-xml

Read me
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0405.html

These HowTo's are about the way XML can be used from Java or directly through a browser (tested with
IE6).

Here some basic definitions related to this technology:

XML(Extensible Markup Language) is a flexible way to create common information formats and share both
the format and the data on the WWW, intranets, and elsewhere.

XSL (Extensible Style Language) is a language for creating a style sheet that describes how data sent over the
Web using XML is to be presented to the user.

XSL-T (XSL Transformations) is a standard way to describe how to transform ( or change) the structure of an
XML document into an XML document with a different structure.

XML-FOP (XSL Formatting Object Processor) is used to transform XML into something else (ex. PDF).

DOM (Document Object Model) represents the XML as hierarchy to simplify the access. JDOM is an
implementation for Java.

SAX (Simple API for XML) is an event-driven interface. The programmer specifies an event that may happen
and, if it does, SAX gets control and handles the situation.

JAXP (Java API for XML Processing) provides basic functionality for reading, manipulating, and generating
XML documents through pure Java APIs.

NOTE: JAXP in JDK 1.4 now includes :

• Document Object Model (DOM) Level 2 , org.w3c.dom


• Simple API For XML Parsing (SAX) 2.0 , org.xml.sax
• XSLT 1.0 , javax.xml.transform

XQL (XML Query Language) is a way to locate and filter the elements (data fields) and text in an XML
document. It is based on the pattern syntax used in the Extensible Stylesheet Language (XSL) and is proposed

XML 1055
Real's HowTo PDF version

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.

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

Display XML using plain HTML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0406.html

Using something called "Data Island", available only on IE AFAIK.

<HTML>
<HEAD><TITLE>Real's java HowTo</TITLE>
</HEAD>
<XML id="HowTo">
<howto>
<topic>
<title>Java</title>
<url>http://www.rgagnon/javahowto.htm</url>
</topic>
<topic>
<title>PowerBuilder</title>
<url>http://www.rgagnon/pbhowto.htm</url>
</topic>
<topic>
<title>Javascript</title>
<url>http://www.rgagnon/jshowto.htm</url>
</topic>
<topic>
<title>VBScript</title>
<url>http://www.rgagnon/vbshowto.htm</url>
</topic>

Read me 1056
Real's HowTo PDF version

</howto>
</XML>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#FF0000"
VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
<TABLE datasrc="#howto">
<THEAD><TR><TH>TOPIC</TH><TH>URL</TH>
</THEAD>
<TR>
<TD><SPAN datafld="title"></SPAN></TD>
<TD><SPAN datafld="url"></SPAN></TD>
</TR>
</TABLE>
</BODY>
</HTML>

See the result here (IE only).

Transform XML into HTML using XSLT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0407.html

[howto.xml]

<?xml version="1.0"?>
<howto>
<topic>
<title>Java</title>
<url>http://www.rgagnon/javahowto.htm</url>
</topic>
<topic>
<title>PowerBuilder</title>
<url>http://www.rgagnon/pbhowto.htm</url>
</topic>
<topic>
<title>Javascript</title>
<url>http://www.rgagnon/jshowto.htm</url>
</topic>
<topic>
<title>VBScript</title>
<url>http://www.rgagnon/vbshowto.htm</url>
</topic>
</howto>

[howto.xsl]

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="/">

Display XML using plain HTML 1057


Real's HowTo PDF version

<html>
<head><title>Real's HowTo</title></head>
<body>
<table border="1">
<tr>
<th>Title</th>
<th>URL</th>
</tr>
<xsl:for-each select="howto/topic">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="url"/></td>
</tr>
</xsl:for-each>
</table>
</body></html>
</xsl:template>
</xsl:stylesheet>

[HowToXSLT.java]

// jdk1.4.1
import javax.xml.transform.*;
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.

Transform XML into HTML using XSLT 1058


Real's HowTo PDF version

Parse using SAX or DOM


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0408.html

DOM (Document Object Model) represents the XML as hierarchy to simplify the access. Since everything is
in memory, it is more ressource intensive.

SAX - creates events and calls callback methods that the programmer write to handle them.

Both examples read this XML data file [howto.xml]

<?xml version="1.0"?>
<howto>
<topic>
<title>Java</title>
<url>http://www.rgagnon/javahowto.htm</url>
</topic>
<topic>
<title>PowerBuilder</title>
<url>http://www.rgagnon/pbhowto.htm</url>
</topic>
<topic>
<title>Javascript</title>
<url>http://www.rgagnon/jshowto.htm</url>
</topic>
<topic>
<title>VBScript</title>
<url>http://www.rgagnon/vbshowto.htm</url>
</topic>
</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.*;

Parse using SAX or DOM 1059


Real's HowTo PDF version

// using SAX
public class HowToListerSAX {
class HowToHandler extends DefaultHandler {
boolean title = false;
boolean url = false;
public void startElement(String nsURI, String strippedName,
String tagName, Attributes attributes)
throws SAXException {
if (tagName.equalsIgnoreCase("title"))
title = true;
if (tagName.equalsIgnoreCase("url"))
url = true;
}

public void characters(char[] ch, int start, int length) {


if (title) {
System.out.println("Title: " + new String(ch, start, length));
title = false;
}
else if (url) {
System.out.println("Url: " + new String(ch, start,length));
url = false;
}
}
}

public void list( ) throws Exception {


XMLReader parser =
XMLReaderFactory.createXMLReader
("org.apache.crimson.parser.XMLReaderImpl");
parser.setContentHandler(new HowToHandler( ));
parser.parse("howto.xml");
}

public static void main(String[] args) throws Exception {


new HowToListerSAX().list( );
}
}

[HowToListerDOM.java]

// 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();

Parse using SAX or DOM 1060


Real's HowTo PDF version

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 "?";
}
}

Parse an XML string


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0573.html

Using DOM and a StringReader.

import javax.xml.parsers.*;
import org.xml.sax.InputSource;
import org.w3c.dom.*;
import java.io.*;

public class ParseXMLString {

public static void main(String arg[]) {


String xmlRecords =
"<data>" +
" <employee>" +
" <name>John</name>" +
" <title>Manager</title>" +

Parse an XML string 1061


Real's HowTo PDF version

" </employee>" +
" <employee>" +
" <name>Sara</name>" +
" <title>Clerk</title>" +
" </employee>" +
"</data>";

try {
DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xmlRecords));

Document doc = db.parse(is);


NodeList nodes = doc.getElementsByTagName("employee");

// iterate the employees


for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);

NodeList name = element.getElementsByTagName("name");


Element line = (Element) name.item(0);
System.out.println("Name: " + getCharacterDataFromElement(line));

NodeList title = element.getElementsByTagName("title");


line = (Element) title.item(0);
System.out.println("Title: " + getCharacterDataFromElement(line));
}
}
catch (Exception e) {
e.printStackTrace();
}
/*
output :
Name: John
Title: Manager
Name: Sara
Title: Clerk
*/

public static String getCharacterDataFromElement(Element e) {


Node child = e.getFirstChild();
if (child instanceof CharacterData) {
CharacterData cd = (CharacterData) child;
return cd.getData();
}
return "?";
}
}

Parse an XML string 1062


Real's HowTo PDF version

Create an XML document with DOM


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0530.html

import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;

public class TestDOM {


public TestDOM() { }
public String doit()
throws javax.xml.parsers.ParserConfigurationException,
javax.xml.transform.TransformerException,
javax.xml.transform.TransformerConfigurationException{

DocumentBuilderFactory factory
= DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
DOMImplementation impl = builder.getDOMImplementation();

Document doc = impl.createDocument(null,null,null);


Element e1 = doc.createElement("howto");
doc.appendChild(e1);

Element e2 = doc.createElement("java");
e1.appendChild(e2);

e2.setAttribute("url","http://www.rgagnon.com/howto.html");

// transform the Document into a String


DOMSource domSource = new DOMSource(doc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
//transformer.setOutputProperty
(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1");
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
java.io.StringWriter sw = new java.io.StringWriter();
StreamResult sr = new StreamResult(sw);
transformer.transform(domSource, sr);
String xml = sw.toString();
return xml;
}

Create an XML document with DOM 1063


Real's HowTo PDF version

public static void main(String args[])


throws javax.xml.parsers.ParserConfigurationException,
javax.xml.transform.TransformerException,
javax.xml.transform.TransformerConfigurationException{
System.out.println(new TestDOM().doit());
/*
output :
<?xml version="1.0" encoding="ISO-8859-1"?>
<howto>
<java url="http://www.ragagnon.com/howto.html"/>
</howto>
/*
}
}

Attach a stylesheet to an XML file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0450.html

Consider the following XML file, a simple xsl is attached to nicely format the data.
Modern browsers (like N7 or IE5.5) support XML and XSL transformation.

bruce.xml

<?xml version="1.0" encoding="ISO-8859-1"?>


<?xml-stylesheet type="text/xsl" href="bruce.xsl"?>
<data>
<guynamedbruce>
<FirstName>Bruce</FirstName>
<LastName>Lee</LastName>
</guynamedbruce>
<guynamedbruce>
<FirstName>Bruce</FirstName>
<LastName>Willis</LastName>
</guynamedbruce>
<guynamedbruce>
<FirstName>Bruce</FirstName>
<LastName>Wayne</LastName>
</guynamedbruce>
</data>

bruce.xsl

<?xml version="1.0" encoding="ISO-8859-1"?>


<xsl:stylesheet version="1.0" xmlns:xsl="http://w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>

Attach a stylesheet to an XML file 1064


Real's HowTo PDF version

<table>
<xsl:for-each select="data/guynamedbruce">
<tr>
<td>
<xsl:value-of select="FirstName"/>
</td>
<td>
<xsl:value-of select="LastName"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

Try it here

Create an XML file and attach an XSL


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0577.html

import java.io.*;

import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;

public class CreateXML {

public static void main (String args[]) {


new CreateXML().doit();
}

public void doit () {


try{
Document xmldoc = initXML();
Element root = xmldoc.getDocumentElement();

process(xmldoc, root);

StreamResult out = new StreamResult("howto.xml");


writeXML(xmldoc, out);
}
catch (Exception e) { e.printStackTrace(); }
}

Create an XML file and attach an XSL 1065


Real's HowTo PDF version

public Document initXML() throws ParserConfigurationException{


// JAXP + DOM
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
DOMImplementation impl = builder.getDOMImplementation();
return impl.createDocument(null, "HOWTOS", null);
}

public void process(Document xmldoc, Element root) {


Element e0 = xmldoc.createElement("TOPIC");

Element e1 = xmldoc.createElement("TITLE");
Node n1 = xmldoc.createTextNode("Java");
e1.appendChild(n1);

Element e2 = xmldoc.createElement("URL");
Node n2 = xmldoc.createTextNode
("http://www.rgagnon/topics/java-xml.html");
e2.appendChild(n2);

e0.appendChild(e1);
e0.appendChild(e2);
root.appendChild(e0);
}

public void writeXML(Document xmldoc, StreamResult out)


throws TransformerConfigurationException, TransformerException
{
DOMSource domSource = new DOMSource(xmldoc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty
(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1");
// we want to pretty format the XML output
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
transformer.transform(domSource, out);
}
}

The result is

<?xml version="1.0" encoding="ISO-8859-1"?>


<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>
<URL>http://www.rgagnon/topics/java-xml.html</URL>
</TOPIC>
</HOWTOS>

Create an XML file and attach an XSL 1066


Real's HowTo PDF version

And now to attach an XSL

import java.io.*;

import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;

public class CreateXML {

public static void main (String args[]) {


new CreateXML().doit();
}

public void doit () {


try{
Document xmldoc = initXML();
Element root = xmldoc.getDocumentElement();

process(xmldoc, root);

Node pi = xmldoc.createProcessingInstruction
("xml-stylesheet", "type=\"text/xsl\" href=\"howto.xsl\"");
xmldoc.insertBefore(pi, root);

StreamResult out = new StreamResult("howto.xml");


writeXML(xmldoc, out);
}
catch (Exception e) { e.printStackTrace(); }
}

public Document initXML() throws ParserConfigurationException{


// JAXP + DOM
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
DOMImplementation impl = builder.getDOMImplementation();
return impl.createDocument(null, "HOWTOS", null);
}

public void process(Document xmldoc, Element root) {


Element e0 = xmldoc.createElement("TOPIC");

Element e1 = xmldoc.createElement("TITLE");
Node n1 = xmldoc.createTextNode("Java");
e1.appendChild(n1);

Element e2 = xmldoc.createElement("URL");
Node n2 = xmldoc.createTextNode
("http://www.rgagnon/topics/java-xml.html");
e2.appendChild(n2);

e0.appendChild(e1);

Create an XML file and attach an XSL 1067


Real's HowTo PDF version

e0.appendChild(e2);
root.appendChild(e0);
}

public void writeXML(Document xmldoc, StreamResult out)


throws TransformerConfigurationException, TransformerException
{
DOMSource domSource = new DOMSource(xmldoc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty
(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1");
// we want to pretty format the XML output
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
transformer.transform(domSource, out);
}
}

The result is

<?xml version="1.0" encoding="ISO-8859-1"?>


<?xml-stylesheet type="text/xsl" href="howto.xsl"?>

<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>
<URL>http://www.rgagnon/topics/java-xml.html</URL>
</TOPIC>
</HOWTOS>

Nicely display WEB.XML informations


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0451.html

A web.xml file contains informations about a web application hosted by a application server. While it's
possible to consult the data using a regular text editor, it maybe easier to use a special stylesheet to nicely
format the data for easy browsing.

I found a nice generic stylesheet on the Web and adapted it a little bit for that purpose. Here the modified xsl
file, the css file, a sample web.xml.

See the sample output if your browser supports XML/XSL transformation.

Nicely display WEB.XML informations 1068


Real's HowTo PDF version

Attach the xsl to the xml by adding this line to the xml file :

<?xml version="1.0" encoding="UTF-8"?>


<?xml-stylesheet type="text/xsl" href="tree-view.xsl"?>
...

or do the transformation in Java, for a hint see this How-to.

Here an ASP page (yeah I know...) which accepts as a parameter an XML filename and transforms the passed
filename using the XSL. As an added bonus, the original XML filename is displayed (you will need this
XSL).
<META http-equiv="Content-Type" content="text/html; charset=ISO8859-1">
<%@ LANGUAGE="JScript" %>
<%
Response.buffer = true;
var xmlfile;
var oXML;
var oXSL;
var oXSLTemplate;
var oXSLProcessor;
var SrcXSL;
var SrcXML;

// get the PARAM=??? (assumes you have used GET request method!)...
// assume something like http://.../docxml.asp?xmlfile=myxml.xml
xmlfile = '' + Request.QueryString('xmlfile');

// get the source file (XML and XSL) paths


SrcXML = Server.MapPath(xmlfile);
SrcXSL = Server.MapPath('xmldoc/tree-view2.xsl');

// create documents for the XML and XSL...


oXML = Server.CreateObject('Msxml2.DOMDocument');
oXSL = Server.CreateObject('Msxml2.FreeThreadedDOMDocument');

// load the XML and XSL into your documents...


// we don't want to waste time validating the file
oXSL.load(SrcXSL);
oXML.validateOnParse = false ;
oXML.async = false ;
oXML.resolveExternals = false ;

oXML.load(SrcXML);

// 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...

Nicely display WEB.XML informations 1069


Real's HowTo PDF version

oXSLProcessor.input = oXML;

try {
oXSLProcessor.transform ;
Response.write(oXSLProcessor.output);
}
catch (e) {
Response.write
('The file ' +e.url + ' is not valid. Reason: ' + e.reason );
}

%&GT;

Serialize an object using XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0470.html

Consider this simple class

public class Foo {


private String foo ;

public void setFoo(String s) {


foo = s;
}

public String getFoo() {


return foo;
}
}

The java.beans package provides useful methods to save an object state into an XML file and easily read it
back.

Here an Helper class for our Foo class.

import java.beans.XMLEncoder;
import java.beans.XMLDecoder;
import java.io.*;

public class FooHelper {


public static void write(Foo f, String filename) throws Exception{
XMLEncoder encoder =
new XMLEncoder(
new BufferedOutputStream(
new FileOutputStream(filename)));
encoder.writeObject(f);
encoder.close();
}

Serialize an object using XML 1070


Real's HowTo PDF version

public static Foo read(String filename) throws Exception {


XMLDecoder decoder =
new XMLDecoder(new BufferedInputStream(
new FileInputStream(filename)));
Foo o = (Foo)decoder.readObject();
decoder.close();
return o;
}
}

Here how to use it.

public class FooTest {


public static void main (String [] args) throws Exception{
Foo f1 = new Foo();
f1.setFoo("bar");
FooHelper.write(f1, "foo.xml");

Foo f2 = FooHelper.read("foo.xml");
System.out.println("Foo" + f2.getFoo());
// the output : Foobar
}
}

Just for fun, here the resulting XML file (with my installation)

<?xml version="1.0" encoding="UTF-8"?>


<java version="1.5.0-beta" class="java.beans.XMLDecoder">
<object class="Foo">
<void property="foo">
<string>bar</string>
</void>
</object>
&LT;/JAVA&GT;

Convert flat file to XML using SAX


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0482.html

Consider the following data file (data.txt):

Java|http://www.rgagnon/javahowto.htm
PowerBuilder|http://www.rgagnon/pbhowto.htm
Javascript|http://www.rgagnon/jshowto.htm
VBScript|http://www.rgagnon/vbshowto.htm

We want to convert it to an XML format (data.xml) :

Convert flat file to XML using SAX 1071


Real's HowTo PDF version

<?xml version="1.0" encoding="ISO-8859-1"?>


<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>
<URL>http://www.rgagnon/javahowto.htm</URL>
</TOPIC>
<TOPIC>
<TITLE>PowerBuilder</TITLE>
<URL>http://www.rgagnon/pbhowto.htm</URL>
</TOPIC>
<TOPIC>
<TITLE>Javascript</TITLE>
<URL>http://www.rgagnon/jshowto.htm</URL>
</TOPIC>
<TOPIC>
<TITLE>VBScript</TITLE>
<URL>http://www.rgagnon/vbshowto.htm</URL>
</TOPIC>
</HOWTOS>

We are using JAXP and SAX.

import java.io.*;

// SAX classes.
import org.xml.sax.*;
import org.xml.sax.helpers.*;

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.sax.*;

public class ToXML {

BufferedReader in;
StreamResult out;

TransformerHandler th;
AttributesImpl atts;

public static void main (String args[]) {


new ToXML().doit();
}

public void doit () {


try{
in = new BufferedReader(new FileReader("data.txt"));
out = new StreamResult("data.xml");
initXML();
String str;
while ((str = in.readLine()) != null) {
process(str);
}

Convert flat file to XML using SAX 1072


Real's HowTo PDF version

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,"ISO-8859-1");
// pretty XML output
serializer.setOutputProperty
("{http://xml.apache.org/xslt}indent-amount", "4");
serializer.setOutputProperty(OutputKeys.INDENT,"yes");
th.setResult(out);
th.startDocument();
atts = new AttributesImpl();
th.startElement("","","HOWTOS",atts);
}

public void process (String s) throws SAXException {


String [] elements = s.split("\\|");
atts.clear();
th.startElement("","","TOPIC",atts);

th.startElement("","","TITLE",atts);
th.characters(elements[0].toCharArray(),0,elements[0].length());
th.endElement("","","TITLE");

th.startElement("","","URL",atts);
th.characters(elements[1].toCharArray(),0,elements[1].length());
th.endElement("","","URL");

th.endElement("","","TOPIC");
}

public void closeXML() throws SAXException {


th.endElement("","","HOWTOS");
th.endDocument(); }
}

Convert flat file to XML using DOM


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0481.html

Convert flat file to XML using DOM 1073


Real's HowTo PDF version

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="ISO-8859-1"?>


<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>
<URL>http://www.rgagnon/javahowto.htm</URL>
</TOPIC>
<TOPIC>
<TITLE>PowerBuilder</TITLE>
<URL>http://www.rgagnon/pbhowto.htm</URL>
</TOPIC>
<TOPIC>
<TITLE>Javascript</TITLE>
<URL>http://www.rgagnon/jshowto.htm</URL>
</TOPIC>
<TOPIC>
<TITLE>VBScript</TITLE>
<URL>http://www.rgagnon/vbshowto.htm</URL>
</TOPIC>
</HOWTOS>

We are using JAXP and DOM.

NOTE: Since DOM constructs the XML tree in memory, it may be more appropriate to use SAX instead if you have to deal with big data files.

import java.io.*;

import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;

public class ToXML {

BufferedReader in;
StreamResult out;

Document xmldoc;
Element root;

public static void main (String args[]) {


new ToXML().doit();
}

Convert flat file to XML using DOM 1074


Real's HowTo PDF version

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);
}

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");

Convert flat file to XML using DOM 1075


Real's HowTo PDF version

transformer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1");
// we want to pretty format the XML output
// note : this is broken in jdk1.5 beta!
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
transformer.transform(domSource, out);
/*
get the XML in a String
java.io.StringWriter sw = new java.io.StringWriter();
StreamResult sr = new StreamResult(sw);
transformer.transform(domSource, sr);
return sw.toString();
*/
}
}

Convert a ResultSet in XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0511.html

import java.sql.Connection;
import java.sql.Statement;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

class JDBCapp {

static Connection con;

public static void main (String args[]) {


ResultSet rs = null;
Statement stmt = null;
String sql;

try {
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();

Convert a ResultSet in XML 1076


Real's HowTo PDF version

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,"ISO-8859-1");
// we want to pretty format the XML output
// note : this is broken in jdk1.5 beta!

Convert a ResultSet in XML 1077


Real's HowTo PDF version

transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
java.io.StringWriter sw = new java.io.StringWriter();
StreamResult sr = new StreamResult(sw);
transformer.transform(domSource, sr);
return sw.toString();
}
}

class AccessCon {
public static Connection getConnection() throws Exception {
Driver d = (Driver)Class.forName
("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
Connection c = DriverManager.getConnection
("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=c:/tech97.mdb");
return c;
/*
To use an already defined ODBC Datasource :

String URL = "jdbc:odbc:myDSN";


Connection c = DriverManager.getConnection(URL, "user", "pwd");

*/
}
}

Parse with XPath


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0550.html

[J2SE 1.5]

Consider the following XML data file (howto.xml)

<?xml version="1.0"?>
<howto>
<topic name="Java">
<url>http://www.rgagnon.com/topics/java-xml.html</url>
</topic>
<topic name="PowerBuilder">
<url>http://www.rgagnon.com/topics/pb-common.html</url>
<url>http://www.rgagnon.com/topics/pb-pfc.html</url>
</topic>
<topic name="Javascript">
<url>http://www.rgagnon.com/topics/js-language.html</url>
</topic>

Parse with XPath 1078


Real's HowTo PDF version

<topic name="VBScript">
<url>http://www.rgagnon.com/topics/wsh-vbs.html</url>
</topic>
</howto>

To list the topics :

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.*;

import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class SimpleXPath {


public static void main(String[] args) throws Exception {
XPath xpath = XPathFactory.newInstance().newXPath();
String xpathExpression = "/howto/topic/@name";
InputSource inputSource = new InputSource("howto.xml");

NodeList nodes = (NodeList) xpath.evaluate


(xpathExpression, inputSource, XPathConstants.NODESET);

int j = nodes.getLength();

for (int i = 0; i < j; i++) {


System.out.println(nodes.item(i).getTextContent());
}
/*
output :
Java
PowerBuilder
Javascript
VBScript
*/
}
}

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 {

Parse with XPath 1079


Real's HowTo PDF version

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/pb-common.html
http://www.rgagnon.com/topics/pb-pfc.html
*/
// display only the "url" nodes for PowerBuidler
NodeList urls = nodes.item(0).getChildNodes();
int j = urls.getLength();
for (int i = 0; i < j ; i++) {
if (urls.item(i).getNodeName().equals("url")) {
System.out.println("url :" + urls.item(i).getTextContent());
}
}
/*
output :
url :http://www.rgagnon.com/topics/pb-common.html
url :http://www.rgagnon.com/topics/pb-pfc.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);
...

Parse with XPath 1080


Real's HowTo PDF version

You may need to pass the required encoding to the String.getBytes() method. See this HowTo

Consider this XML :


<?xml version="1.0" encoding="UTF-8"?>
<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 java.io.ByteArrayInputStream;
import java.io.InputStream;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
import org.xml.sax.InputSource;

...

String xml = "<?xml version="1.0" encoding="UTF-8"?>"


+ "<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>

Parse with XPath 1081


Real's HowTo PDF version

</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=?
*/

Strip extra spaces in a XML string


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0563.html

This can be useful to reduce the size of a file or before writting a message to a queue or the network.

public class XMLStripSpaces {


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 :

Strip extra spaces in a XML string 1082


Real's HowTo PDF version

<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>
*/
}
}

One drawback is that the spaces inside tags are stripped too. The following example preserves those spaces
inside a tag.

public class XMLStripSpaces {


public static void main (String [] args) {
String test1 = "<tag>test 1</tag> <tag>test 2</tag> <tag> </tag>";
String out1 = test1.replaceAll("(?!>\\s+</)(>\\s+<)", "><");
System.out.println(test1);
System.out.println(out1);

/*
output :
<tag>test 1</tag> <tag>test 2</tag> <tag> </tag>
<tag>test 1</tag><tag>test 2</tag><tag> </tag>

*/
}
}

Create an XML file and attach an XSL


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0577.html

import java.io.*;

import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;

public class CreateXML {

public static void main (String args[]) {


new CreateXML().doit();
}

Create an XML file and attach an XSL 1083


Real's HowTo PDF version

public void doit () {


try{
Document xmldoc = initXML();
Element root = xmldoc.getDocumentElement();

process(xmldoc, root);

StreamResult out = new StreamResult("howto.xml");


writeXML(xmldoc, out);
}
catch (Exception e) { e.printStackTrace(); }
}

public Document initXML() throws ParserConfigurationException{


// JAXP + DOM
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
DOMImplementation impl = builder.getDOMImplementation();
return impl.createDocument(null, "HOWTOS", null);
}

public void process(Document xmldoc, Element root) {


Element e0 = xmldoc.createElement("TOPIC");

Element e1 = xmldoc.createElement("TITLE");
Node n1 = xmldoc.createTextNode("Java");
e1.appendChild(n1);

Element e2 = xmldoc.createElement("URL");
Node n2 = xmldoc.createTextNode
("http://www.rgagnon/topics/java-xml.html");
e2.appendChild(n2);

e0.appendChild(e1);
e0.appendChild(e2);
root.appendChild(e0);
}

public void writeXML(Document xmldoc, StreamResult out)


throws TransformerConfigurationException, TransformerException
{
DOMSource domSource = new DOMSource(xmldoc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty
(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1");
// we want to pretty format the XML output
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//

Create an XML file and attach an XSL 1084


Real's HowTo PDF version

transformer.transform(domSource, out);
}
}

The result is

<?xml version="1.0" encoding="ISO-8859-1"?>


<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>
<URL>http://www.rgagnon/topics/java-xml.html</URL>
</TOPIC>
</HOWTOS>

And now to attach an XSL

import java.io.*;

import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;

public class CreateXML {

public static void main (String args[]) {


new CreateXML().doit();
}

public void doit () {


try{
Document xmldoc = initXML();
Element root = xmldoc.getDocumentElement();

process(xmldoc, root);

Node pi = xmldoc.createProcessingInstruction
("xml-stylesheet", "type=\"text/xsl\" href=\"howto.xsl\"");
xmldoc.insertBefore(pi, root);

StreamResult out = new StreamResult("howto.xml");


writeXML(xmldoc, out);
}
catch (Exception e) { e.printStackTrace(); }
}

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);

Create an XML file and attach an XSL 1085


Real's HowTo PDF version

public void process(Document xmldoc, Element root) {


Element e0 = xmldoc.createElement("TOPIC");

Element e1 = xmldoc.createElement("TITLE");
Node n1 = xmldoc.createTextNode("Java");
e1.appendChild(n1);

Element e2 = xmldoc.createElement("URL");
Node n2 = xmldoc.createTextNode
("http://www.rgagnon/topics/java-xml.html");
e2.appendChild(n2);

e0.appendChild(e1);
e0.appendChild(e2);
root.appendChild(e0);
}

public void writeXML(Document xmldoc, StreamResult out)


throws TransformerConfigurationException, TransformerException
{
DOMSource domSource = new DOMSource(xmldoc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty
(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1");
// we want to pretty format the XML output
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
transformer.transform(domSource, out);
}
}

The result is

<?xml version="1.0" encoding="ISO-8859-1"?>


<?xml-stylesheet type="text/xsl" href="howto.xsl"?>

<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>
<URL>http://www.rgagnon/topics/java-xml.html</URL>
</TOPIC>
</HOWTOS>

Create an XML file and attach an XSL 1086


Real's HowTo PDF version

Use XML with Properties


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0578.html

import java.util.*;
import java.io.*;

class XMLProps {
public static void main(String args[]) {
new XMLProps().doit();
}

public void doit() {


try{
Properties p = new Properties();

p.put("today", new Date().toString());


p.put("user", "Bob");

FileOutputStream out = new FileOutputStream("user.props");


p.storeToXML(out,"props updated");

FileInputStream in = new FileInputStream("user.props");

p.loadFromXML(in);
p.list(System.out);
/*
output :
-- listing properties --
today=Thu Aug 09 22:45:11 EDT 2007
user=Bob
*/
}
catch (Exception e) {
e.printStackTrace();
}
}
}

The XML looks like

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>props updated</comment>
<entry key="user">Bob</entry>
<entry key="today">Thu Aug 09 22:45:11 EDT 2007</entry>
</properties>

Use XML with Properties 1087


Real's HowTo PDF version

Change a particular node in XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0625.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;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import 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);

Change a particular node in XML 1088


Real's HowTo PDF version

// 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="UTF-8" standalone="no"?><data>


<employee>
<name>John Paul</name>
<title>Manager</title>
</employee>
<employee>
<name>Sara</name>
<title>Clerk</title>
</employee>
</data>

Validate XML using a DTD


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0668.html

Consider this XML file howto.xml :

<?xml version="1.0" encoding="ISO-8859-1"?>


<!DOCTYPE howto SYSTEM "howto.dtd">
<howto>
<topic>
<title>Java</title>
<url>http://www.rgagnon.com/topics/java-xml.html</url>
</topic>
<topic>
<title>PowerBuilder</title>
<url>http://www.rgagnon.com/topics/pb-powerscript.htm</url>
</topic>
<topic>
<title>Javascript</title>
<url>http://www.rgagnon.com/topics/js-language.html</url>
</topic>
<topic>
<title>VBScript</title>
<url>http://www.rgagnon.com/topics/wsh-vbs.html</url>

Validate XML using a DTD 1089


Real's HowTo PDF version

</topic>
</howto>

A referenced to the external DTD file howto.dtd is present.

The external howto.dtd :

<!ELEMENT howto (topic*)>


<!ELEMENT topic (title,url)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT url (#PCDATA)>

NOTE : The DTD can be inside the XML document.

<?xml version="1.0" encoding="ISO-8859-1"?>


<!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/java-xml.html</url>
</topic>
...
</howto>

The code to validate an XML file using the declared DTD :

import java.io.IOException;
// DOM
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
// SAX
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.XMLReader;

import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.InputSource;

public class XMLUtils {

private XMLUtils() {}

// validate using DOM (DTD as defined in the XML)


public static boolean validateWithDTDUsingDOM(String xml)

Validate XML using a DTD 1090


Real's HowTo PDF version

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();

XMLReader reader = parser.getXMLReader();

Validate XML using a DTD 1091


Real's HowTo PDF version

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

Validate XML using a DTD 1092


Real's HowTo PDF version

Validate XML using a XSD (XML schema)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0669.html

Consider this XML file howto.xml :

<?xml version="1.0" encoding="ISO-8859-1"?>


<howto xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<topic>
<title>Java</title>
<url>http://www.rgagnon.com/topics/java-xml.html</url>
</topic>
<topic>
<title>PowerBuilder</title>
<url>http://www.rgagnon.com/topics/pb-powerscript.htm</url>
</topic>
<topic>
<title>Javascript</title>
<url>http://www.rgagnon.com/topics/js-language.html</url>
</topic>
<topic>
<title>VBScript</title>
<url>http://www.rgagnon.com/topics/wsh-vbs.html</url>
</topic>
</howto>

The external howto.xsd :

<?xml version="1.0" encoding="ISO-8859-1"?>


<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>

Validate XML using a XSD (XML schema) 1093


Real's HowTo PDF version

</xs:simpleType>

</xs:schema>

The code (using SAX parser) to validate an XML file using a given external XSD.

import java.io.IOException;

// SAX
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 javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import 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
}

Validate XML using a XSD (XML schema) 1094


Real's HowTo PDF version

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.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="ISO-8859-1"?>
<howto xsi:noNamespaceSchemaLocation="howto.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<topic>
<title>Java</title>
<url>http://www.rgagnon.com/topics/java-xml.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;

Validate XML using a XSD (XML schema) 1095


Real's HowTo PDF version

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import 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 {
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 XML using a XSD (XML schema) 1096


Real's HowTo PDF version

}
}

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 java.io.IOException;
// SAX
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.XMLReader;

import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.InputSource;

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);
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;
}

Validate XML using a XSD (XML schema) 1097


Real's HowTo PDF version

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 built-in XML parser, you can switch JAXP in debug mode by passing a special
switch on the JVM command-line.

java -Djaxp.debug=1 ...


or
java -Djaxp.debug ...

JAXP will produce log entries about its activities :

JAXP: found null in $java.home/jaxp.properties


JAXP: no META-INF/services/javax.xml.validation.SchemaFactory file was found
JAXP: attempting to use the platform default XML Schema validator
JAXP: createInstance(com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory)
...

NOTES :
• 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.

Validate XML using a XSD (XML schema) 1098


Real's HowTo PDF version

Sanitize XML String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-sanitize-xml-string.html

The following lists the range of valid XML characters. Any character not in the range is not allowed.

Hexidecimal Decimal
#x9 #9
#xA #10
#xD #13
#x20-#xD7FF #32-#55295
#xE000-#xFFFD #57344-#65533
#x10000-#x10FFFF #10000-#1114111
any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.

ref : http://www.w3.org/TR/REC-xml/#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/REC-xml/#charsets
// jdk 7
Pattern xmlInvalidChars =
Pattern.compile(
"[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\\x{10000}-\\x{10FFFF}]"

);
return xmlInvalidChars.matcher(xml).replaceAll("");
}

Using StringBuilder and for-loop

public static String sanitizeXmlChars(String in) {


StringBuilder out = new StringBuilder();

Sanitize XML String 1099


Real's HowTo PDF version

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();
}

Produce HTML entities when using XSLT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-produce-HTML-entities-when-using-XSLT.html

You disable the automatic output escaping and use the &amp; entity to build the actual entity.

<P><span style="border-style:solid;border-width:1px;">
<a href="{link}">
<xsl:text disable-output-escaping="yes">&amp;nbsp;&amp;rArr;</xsl:text>
Read the article</a>.
<xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
</span>
</P>

will produce

⇒Read the article.

Transform XML into CSV using XSLT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-transform-xml-into-csv-using-xslt.html

The input file


[howto.xml]

<?xml version="1.0"?>
<howto>
<topic id="1">
<title>Java</title>

Produce HTML entities when using XSLT 1100


Real's HowTo PDF version

<url>http://www.rgagnon.com/topics/java-io.html</url>
</topic>
<topic id="2">
<title>XML</title>
<url>http://www.rgagnon.com/topics/java-xml.html</url>
</topic>
<topic id="3">
<title>Javascript</title>
<url>http://www.rgagnon.com/topics/js-language.html</url>
</topic>
<topic id="4">
<title>VBScript</title>
<url>http://www.rgagnon.com/topics/wsh-vbs.html</url>
</topic>
</howto>

The transformation sheet


[howto.xsl]

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format" >
<xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
<xsl:template match="/">
topic,title,url
<xsl:for-each select="//topic">
<xsl:value-of select="@id" />
<xsl:value-of select="concat(',' , title, ',' , url,'
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Using this program


[XMLToCSV.java]

package com.rgagnon.howto;

import org.w3c.dom.Document;
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class XMLToCSV {


public static void main(String args[]) throws Exception {
File stylesheet = new File("src/howto.xsl");
File xmlSource = new File("src/howto.xml");

Transform XML into CSV using XSLT 1101


Real's HowTo PDF version

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();


DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(xmlSource);

StreamSource stylesource = new StreamSource(stylesheet);


Transformer transformer = TransformerFactory.newInstance()
.newTransformer(stylesource);
Source source = new DOMSource(document);
Result outputTarget = new StreamResult(new File("/temp/howto.csv"));
transformer.transform(source, outputTarget);
System.out.println("Done.");
}
}

The result is
[howoto.csv]

topic,title,url
1,Java,http://www.rgagnon.com/topics/java-io.html
2,XML,http://www.rgagnon.com/topics/java-xml.html
3,Javascript,http://www.rgagnon.com/topics/js-language.html
4,VBScript,http://www.rgagnon.com/topics/wsh-vbs.html

Create a RSS feed (part 1)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0556.html

RSS is a method to syndicate content on the web. This is done by creating an XML document which
summarizes specific content such as news, blog posts or comments or any informations. There are many
versions but the 2 most used are RSS 2.0 and ATOM.

RSS 2.0

The official specification of RSS 2.0 : http://cyber.law.harvard.edu/rss/rss.html

Create a RSS feed (part 1) 1102


Real's HowTo PDF version

A typical RSS XML file looks like :

<?xml version="1.0" encoding="utf-8"?>


<?xml-stylesheet title="XSL_formatting" type="text/xsl" href="feed.xsl"?>

<rss version="2.0">

<channel>
<title>Real's HowTo</title>
<description>Updates of useful code examples for Java</description>
<link>http://www.rgagnon.com/howto.html</link>
<pubDate>23 May 2007 00:00:00 GMT</pubDate>
<image>
<title>Real's HowTo</title>
<width>144</width>
<height>41</height>
<link>http://www.rgagnon.com/howto.html</link>
<url>http://www.rgagnon.com/images/realhowto-left.jpg</url>
</image>

<item>
<title>JS: Resize an IFRAME based on its content</title>
<description>Using the onLoad event, resize the IFRAME</description>
<link>http://www.rgagnon.com/jsdetails/js-0129.html</link>
<pubDate>23 May 2007 00:00:00 GMT</pubDate>
<guid>http://www.rgagnon.com/jsdetails/js-0129.html</guid>
</item>

</channel>
</rss>

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.

Create a RSS feed (part 1) 1103


Real's HowTo PDF version

A typical ATOM feed looks like :

<?xml version="1.0" encoding="utf-8"?>


<feed xmlns="http://www.w3.org/2005/Atom">

<title>Example Feed</title>
<subtitle>A subtitle.</subtitle>
<link href="http://example.org/"/>
<updated>2003-12-13T18:30:02Z</updated>
<author>
<name>John Doe</name>
<email>[email protected]</email>
</author>
<id>urn:uuid:60a76c80-d399-11d9-b91C-0003939e0af6</id>

<entry>
<title>Atom-Powered Robots Run Amok</title>
<link href="http://example.org/2003/12/13/atom03"/>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
<updated>2003-12-13T18:30:02Z</updated>
<summary>Some text.</summary>
</entry>

Create a RSS feed (part 1) 1104


Real's HowTo PDF version

</feed>

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.

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-summary.h

So you need the main Commons Digester plus, as usual with Apache software, you have depencies with the
BeanUtils v1.7 and Commons Logging

Download the required jars at http://jakarta.apache.org/commons/digester/

Don't forget the famous commons-digester-rss.jar, you can build it from the Commons Digester examples
jar or download it from here.

import org.apache.commons.digester.rss.Channel;
import org.apache.commons.digester.rss.Item;
import org.apache.commons.digester.rss.RSSDigester;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.text.SimpleDateFormat;

class CreateRSSFeedUsingCommons {

public static void main(String args[]) {

SimpleDateFormat formatter=
new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z");
String today = formatter.format(new Date());

Channel newChannel = new Channel();

Create a RSS feed (part 1) 1105


Real's HowTo PDF version

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);

Item item = new Item();


item.setTitle("Real's HowTo");
item.setLink("http://www.rgagnon.com/java-details/");
item.setDescription("Cool java snippet!");
newChannel.setPubDate(today);
newChannel.addItem(item);

try {
FileOutputStream fout = new FileOutputStream("feed.xml");
newChannel.render(fout);
fout.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}

The result is :

<?xml version="1.0"?>

<!DOCTYPE rss PUBLIC


"-//Netscape Communications//DTD RSS 0.91//EN"
"http://my.netscape.com/publish/formats/rss-0.91.dtd">

<rss version="0.91">

<channel>

<title>null</title>
<description>Useful Java code examples</description>
<link>http://www.rgagnon.com/howto.html</link>
<language>en</language>
<copyright>(c)Real Gagnon 2007</copyright>
<pubDate>29 mai 2007 23:48:42 -0400</pubDate>

<item>
<title>Real's HowTo</title>
<link>http://www.rgagnon.com/java-details/</link>
<description>Cool java snippet!</description>
</item>

</channel>

</rss>

Create a RSS feed (part 1) 1106


Real's HowTo PDF version

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!

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/).

import com.sun.syndication.feed.synd.*;
import com.sun.syndication.io.SyndFeedOutput;

import java.io.FileWriter;
import java.io.Writer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

public class CreateRSSFeedUsingRome {


private static final DateFormat DATE_PARSER =
new SimpleDateFormat("yyyy-MM-dd");

public static void main(String[] args) {


try {
String feedType = "rss_2.0";
String fileName = "feed.xml";

SyndFeed feed = new SyndFeedImpl();


feed.setFeedType(feedType);

feed.setTitle("Real's HowTo");
feed.setLink("http://www.rgagnon.com/howto.html");
feed.setDescription("Useful Java code examples");

List entries = new ArrayList();


SyndEntry entry;
SyndContent description;

entry = new SyndEntryImpl();


entry.setTitle("Real's HowTo");
entry.setLink("http://www.rgagnon.com/java-details/");
entry.setPublishedDate(DATE_PARSER.parse("2004-06-08"));
description = new SyndContentImpl();
description.setType("text/plain");
description.setValue("Cool java snippet!");
entry.setDescription(description);
entries.add(entry);

Create a RSS feed (part 1) 1107


Real's HowTo PDF version

feed.setEntries(entries);

Writer writer = new FileWriter(fileName);


SyndFeedOutput output = new SyndFeedOutput();
output.output(feed,writer);
writer.close();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}

And the result is :

<?xml version="1.0" encoding="UTF-8"?>


<rss xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
<channel>
<title>Real's HowTo</title>
<link>http://www.rgagnon.com/howto.html</link>
<description>Useful Java code examples</description>
<item>
<title>Real's HowTo</title>
<link>http://www.rgagnon.com/java-details/</link>
<description>Cool java snippet!</description>
<pubDate>Tue, 08 Jun 2004 04:00:00 GMT</pubDate>
<guid>http://www.rgagnon.com/java-details/</guid>
<dc:date>2004-06-08T04:00:00Z</dc:date>
</item>
</channel>
</rss>

Create a RSS feed (part 2)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0608.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;

Create a RSS feed (part 2) 1108


Real's HowTo PDF version

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;
}
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() {

Create a RSS feed (part 2) 1109


Real's HowTo PDF version

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;
}
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) {

Create a RSS feed (part 2) 1110


Real's HowTo PDF version

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 java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import 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());
}
}

A class to build the XML

package com.rgagnon.howto.rss;

import java.io.FileOutputStream;
import java.util.Iterator;

Create a RSS feed (part 2) 1111


Real's HowTo PDF version

import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartDocument;
import javax.xml.stream.events.StartElement;
import 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);

Create a RSS feed (part 2) 1112


Real's HowTo PDF version

writer.add(eventFactory.createEndElement("", "", "channel"));


writer.add(endSection);
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>();

Create a RSS feed (part 2) 1113


Real's HowTo PDF version

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");
entry.setGuid("http://www.rgagnon.com/javadetails/java-0605.html");
entry.setLink("http://www.rgagnon.com/javadetails/java-0605.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/java-0605.html</link>
<guid>http://www.rgagnon.com/javadetails/java-0605.html</guid>
<pubDate>Mon, 23 Jun 2008 11:15:31 -0400</pubDate>
</item>

Create a RSS feed (part 2) 1114


Real's HowTo PDF version

</channel>
</rss>

Parse a RSS XML file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0557.html

In a previous HowTo, we saw how to create a RSS feed using commons.digester or ROME packages. In
this HowTo, we are parsing a given feed using the packages.

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);

Parse a RSS XML file 1115


Real's HowTo PDF version

...
*/
}
}

the output

JS: Resize an IFRAME based on its content


http://www.rgagnon.com/jsdetails/js-0129.html
Using the onLoad event, resize the IFRAME according to its content

Java: Communicate between threads using a Queue


http://www.rgagnon.com/javadetails/java-0555.html
BlockingQueue (Java 5) is designed to work in a multi-threaded world

JDBC: Escape special character in a LIKE clause


http://www.rgagnon.com/javadetails/java-0554.html
How to use LIKE clause wildcards as literals
...

Parsing a feed with ROME

NOTE: See this HowTo for the required jars.

import com.sun.syndication.feed.synd.*;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;

import java.net.URL;
import java.util.List;
import java.util.Iterator;

public class ParseRSSFeedUsingRome {


public static void main(String args[]) throws Exception {
String feed = "http://www.rgagnon.com/feed.xml";

URL feedUrl = new URL(feed);

SyndFeedInput input = new SyndFeedInput();


SyndFeed sf = input.build(new XmlReader(feedUrl));

List entries = sf.getEntries();


Iterator it = entries.iterator();
while (it.hasNext()) {
SyndEntry entry = (SyndEntry)it.next();
System.out.println(entry.getTitle());
System.out.println(entry.getLink());
SyndContent description = entry.getDescription();
System.out.println(description.getValue());
System.out.println();
}
/*

Parse a RSS XML file 1116


Real's HowTo PDF version

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));
*/
}
}

RSS-UTIL.TLD

A Sun article about a JSP Tag Library to parse a RSS feed.


http://java.sun.com/developer/technicalArticles/javaserverpages/rss_utilities/

Add a Live bookmark


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0558.html

Live Bookmark is used to subscribe easily to the RSS feed from a particular web site. A Live bookmark is
possible if you see an orange icon in the address bar. Simply click on the icon and then a live bookmark is
created.

Most modern browsers have something like that like FF or IE7.

To make the icon appear, add this directive your page(s).

<LINK rel="alternate" type="application/rss+xml"


title="Real's HowTo" href="http://www.rgagnon.com/feed.xml">

Validate a RSS feed


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0559.html

To make sure your generated RSS feed is ok, use this very handy site : http://feedvalidator.org/.

It works with RSS 0.90, 0.91, 0.92, 0.93, 0.94, 1.0, 1.1, and 2.0. It also validates Atom feeds.

Parse a RSS XML file 1117


Real's HowTo PDF version

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.

Attach a CSS to RSS feed


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-0560.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.

You add a directive to the XML file.

<?xml version="1.0" encoding="utf-8"?>


<?xml-stylesheet title="XSL_formatting" type="text/xsl" href="feed.xsl"?>

<rss version="2.0">
...

then, in the XSL

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="channel">
<html>
<head>
<link title="mystyle" href="howto.css"
type="text/css" rel="stylesheet"/>
<link rel='alternate' type='application/rss+xml'
title="Real's HowTo" href='http://www.rgagnon.com/feed.xml'/>
<title>What's new - Real's HowTo</title>
<script type="text/javascript" src="scripts/rss.js" />
<style>
.box {
border-width: 1px 1px 1px 1px;
border-spacing: 2px;
border-style: solid solid solid solid;
border-color: blue blue blue blue;
border-collapse: separate;
background-color: white;
}
</style>

</head>
<body onload="setURLS();">

Validate a RSS feed 1118


Real's HowTo PDF version

<a href='http://www.rgagnon.com/howto.html'
title='Useful code snippets for Java, JS or PB developers!'>
<img src='images/realhowto-left.jpg' border='0' />
</a>
<h2>What's new, the last 10 updates</h2>
<div class="box" align="center">
Copy the URL in the box below into your preferred RSS reader.
New content will be delivered as it's published.

<br/>
<input type="text" size="50" id="rss-url"/>
</div>
<br/>
<xsl:for-each select="item">
<h4><xsl:value-of select="title"/></h4>
<i><xsl:value-of select="pubDate"/></i><br/>
<xsl:value-of select="description"/><br/>
<a HREF="{link}"><xsl:value-of select="link"/></a>
<p/>
</xsl:for-each>
<p/>
<hr/>
<div align="center">
Written and compiled by Real Gagnon ©1998-2007<br/>
[<A HREF="http://www.rgagnon.com/" TARGET="_top"> home </A>]
</div>
</body></html>
</xsl:template>
</xsl:stylesheet>

See the result.

Handle JSON Object


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java-handle-json-object.html

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read
and write. It is used primarily to transmit data between a server and web application, as an alternative to
XML.

JSON structures are easy to manipulate from Java. The required libraries are now included in the Java EE 7
specification.

Create a JSON object from a String

In this HowTo, we create a JSON object from a String.

In a MAVEN project, add this dependency

Attach a CSS to RSS feed 1119


Real's HowTo PDF version

<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.4</version>
</dependency>

or download the jars from https://jsonp.java.net/download.html

import java.io.StringReader;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;

// https://jsonp.java.net/download.html
public class Json1 {
String jsonString = "{" +
" \"firstName\": \"John\", \"lastName\": \"Smith\", \"age\": 25," +
" \"address\" : { " +
" \"streetAddress\": \"21 2nd Street\"," +
" \"city\": \"New York\"," +
" \"state\": \"NY\"," +
" \"postalCode\": \"10021\"" +
" }," +
" \"phoneNumber\": [" +
" { \"type\": \"home\", \"number\": \"212 555-1234\" }," +
" { \"type\": \"fax\", \"number\": \"646 555-4567\" }" +
" ]" +
"}";

public static void main(String args[]) {


Json1 x = new Json1();
x.doit();
}

public void doit() {


JsonReader reader = Json.createReader(new StringReader(jsonString));
JsonObject object = reader.readObject();
reader.close();
System.out.println(object.getString("firstName") + " " + object.getString("lastName"))
System.out.println(object.getJsonObject("address").getString("city")) ;
/*
output :
John Smith
New York
*/
}
}

Create a JSON object from a File

To use a file, replace the StringReader by a FileReader.

Handle JSON Object 1120


Real's HowTo PDF version

Create a JSON object from code

Now, we want to create the JSON object from code.

import javax.json.Json;
import javax.json.JsonObject;

public class Json2 {


public static void main(String args[]) {
Json2 x = new Json2();
x.doit();
}

public void doit() {


JsonObject object = Json.createObjectBuilder()
.add("firstName", "John")
.add("lastName", "Smith")
.add("age", 25)
.add("address", Json.createObjectBuilder()
.add("streetAddress", "21 2nd Street")
.add("city", "New York")
.add("state", "NY")
.add("postalCode", "10021"))
.add("phoneNumber", Json.createArrayBuilder()
.add(Json.createObjectBuilder()
.add("type", "home")
.add("number", "212 555-1234"))
.add(Json.createObjectBuilder()
.add("type", "fax")
.add("number", "646 555-4567")))
.build();

System.out.println(object.getString("firstName") + " " + object.getString("lastName"))


System.out.println(object.getJsonObject("address").getString("city")) ;
}
}

Create a JSON object from a REST service response

To call the REST service, we will use the HTTPClient module from Apache.

In a MAVEN project, add these dependencies

<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.4</version>
</dependency>

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.5</version>

Handle JSON Object 1121


Real's HowTo PDF version

</dependency>

or download the required jars from :

• https://jsonp.java.net/download.html
• http://hc.apache.org/downloads.cgi

For the demonstration, we call http://jsonplaceholder.typicode.com/ which is Fake Online REST API for
Testing and Prototyping.

The first example calls jsonplaceholder.typicode.com/posts/1 to get the first message. From the response,
we extract the id and the title.

The raw response looks like

{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit ...eveniet architecto"
}

import java.io.InputStreamReader;

import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;

import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

public class Json3 {


public static void main(String args[]) throws Exception {
Json3 x = new Json3();
x.doit();
}

public void doit() throws Exception {


JsonReader reader = null;
CloseableHttpClient client = HttpClientBuilder.create().build();
HttpHost target = new HttpHost("jsonplaceholder.typicode.com", 80, "http");
HttpGet request = new HttpGet("/posts/1");
request.addHeader("accept", "application/json");
CloseableHttpResponse response = null;
try {
response = client.execute(target, request);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {

Handle JSON Object 1122


Real's HowTo PDF version

throw new Exception("Failed : HTTP error code : "


+ response.getStatusLine().getStatusCode());
}

reader = Json.createReader(new InputStreamReader((response.getEntity().getContent())


JsonObject object = reader.readObject();

// System.out.println("raw : " + object.toString()) ;


System.out.println("id : " + object.getJsonNumber("id")) ;
System.out.println("title : " + object.getString("title")) ;
/*
output
id : 1
title : sunt aut facere repellat provident occaecati excepturi optio reprehende
Done.
*/
}
finally {
if (reader != null) reader.close();
if (client != null) client.close();
if (response != null) response.close();
System.out.println("Done.");
}
}
}

Now we call jsonplaceholder.typicode.com/posts which returns a message list of 100 elements. From the
response, we iterate the returned array to display the id and the title.

The raw response looks like

[
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit ...eveniet architecto"
}
...
{
"userId": 10,
"id": 100,
"title": "at nam consequatur ea labore ea harum",
"body": "cupiditate quo est a modi nesciunt ... ratione error aut"
}
]

import java.io.InputStreamReader;

import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonReader;

Handle JSON Object 1123


Real's HowTo PDF version

import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

public class Json4 {


public static void main(String args[]) throws Exception {
Json4 x = new Json4();
x.doit();
}

public void doit() throws Exception {


JsonReader reader = null;
CloseableHttpClient client = HttpClientBuilder.create().build();
HttpHost target = new HttpHost("jsonplaceholder.typicode.com", 80, "http");
HttpGet request = new HttpGet("/posts");
request.addHeader("accept", "application/json");
CloseableHttpResponse response = null;
try {
response = client.execute(target, request);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new Exception("Failed : HTTP error code : "
+ response.getStatusLine().getStatusCode());
}

reader = Json.createReader(new InputStreamReader((response.getEntity().getContent())


JsonArray array = reader.readArray();

for (int j = 0; j < array.size(); j++ ) {


JsonObject jo = array.getJsonObject(j);
System.out.println("id : " + jo.getJsonNumber("id")) ;
System.out.println("title : " + jo.getString("title")) ;
}
/*
output
id : 1
title : sunt aut facere repellat provident occaecati excepturi optio reprehende
...
id : 100
title : at nam consequatur ea labore ea harum
Done.
*/
}
finally {
if (reader != null) reader.close();
if (client != null) client.close();
if (response != null) response.close();
System.out.println("Done.");
}
}
}

Handle JSON Object 1124


Real's HowTo PDF version

The same operation using JsonParser and InputStream

import java.io.InputStream;

import javax.json.Json;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;

import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

//https://jsonp.java.net/download.html
//http://hc.apache.org/downloads.cgi

public class Json5 {

public static void main(String args[]) throws Exception {


Json5 x = new Json5();
x.doit();
}

public void doit() throws Exception {


CloseableHttpClient client = HttpClientBuilder.create().build();
HttpHost target = new HttpHost("jsonplaceholder.typicode.com", 80, "http");
HttpGet request = new HttpGet("/posts");
request.addHeader("accept", "application/json");
CloseableHttpResponse response = null;
try {
response = client.execute(target, request);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new Exception("Failed : HTTP error code : "
+ response.getStatusLine().getStatusCode());
}

InputStream is = response.getEntity().getContent();
JsonParser parser = Json.createParser(is);
while (parser.hasNext()) {
Event e = parser.next();
if (e == Event.KEY_NAME) {
switch (parser.getString()) {
case "id":
parser.next();
System.out.print(parser.getString());
System.out.print(": ");
break;
case "title":
parser.next();
System.out.println(parser.getString());
System.out.println("---------");

Handle JSON Object 1125


Real's HowTo PDF version

break;
}
}
}
/*
output :
1: sunt aut facere repellat provident occaecati excepturi optio reprehenderit
-------------
2: qui est esse
---------
...
99: temporibus sit alias delectus eligendi possimus magni
---------
100: at nam consequatur ea labore ea harum
---------
Done.
*/
}
finally {
if (client != null) client.close();
if (response != null) response.close();
System.out.println("Done.");
}
}
}

Create a Java object from a JSON object

It's possible to do it by hand by calling the jasonobject.get[type] and the corresponding DTO/POJO set
methods. But it is easier to use a library to handle the finer details. One library which is nice is GSON.

In Maven project, use

<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
</dependency>

or download the jar from here

Again from our REST example at jsonplaceholder.typicode.com/posts/1 , we define a DTO/POJO as :

public class JsonPlaceHolderPosts {


int userid;
int id;
String title;
String body;

public int getUserid() {


return userid;
}

Handle JSON Object 1126


Real's HowTo PDF version

public void setUserid(int userid) {


this.userid = userid;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}

and then from a JSON stream, we create the Java object

import java.io.InputStreamReader;

import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

import com.google.gson.Gson;

// https://jsonp.java.net/download.html
// http://hc.apache.org/downloads.cgi
// http://search.maven.org/#artifactdetails|com.google.code.gson|gson|2.3.1|jar

public class Json6 {

public static void main(String args[]) throws Exception {


Json6 x = new Json6();
x.doit();
}

public void doit() throws Exception {


CloseableHttpClient client = HttpClientBuilder.create().build();
HttpHost target = new HttpHost("jsonplaceholder.typicode.com", 80, "http");
HttpGet request = new HttpGet("/posts/1");
request.addHeader("accept", "application/json");
CloseableHttpResponse response = null;
try {

Handle JSON Object 1127


Real's HowTo PDF version

response = client.execute(target, request);


if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new Exception("Failed : HTTP error code : "
+ response.getStatusLine().getStatusCode());
}

Gson gson = new Gson();


JsonPlaceHolderPosts jphp = gson.fromJson(new InputStreamReader
(response.getEntity().getContent()), JsonPlaceHolderPosts.class);
System.out.println("id : " + jphp.getId()) ;
System.out.println("title : " + jphp.getTitle()) ;
/*
ouput:
id : 1
title : sunt aut facere repellat provident occaecati excepturi optio reprehende
Done.
*/
}
finally {
if (client != null) client.close();
if (response != null) response.close();
System.out.println("Done.");
}
}
}

Create a JSON string from a Java object

Finally, from a Java object, create a JSON string.

import com.google.gson.Gson;

// http://search.maven.org/#artifactdetails|com.google.code.gson|gson|2.3.1|jar

public class Json7 {

public static void main(String args[]) throws Exception {


Json7 x = new Json7();
x.doit();
}

public void doit() throws Exception {


JsonPlaceHolderPosts jphp = new JsonPlaceHolderPosts();
jphp.setUserid(1111);
jphp.setId(2222);
jphp.setTitle("foo");
jphp.setBody("bar");

Gson gson = new Gson();


String json = gson.toJson(jphp, JsonPlaceHolderPosts.class);
System.out.println("json : " + json) ;
System.out.println("Done.");
/*
output :

Handle JSON Object 1128


Real's HowTo PDF version

json : {"userid":1111,"id":2222,"title":"foo","body":"bar"}
Done.
*/
}
}

Written and compiled Réal Gagnon ©2015 [email protected]


http://www.rgagnon.com

Handle JSON Object 1129

You might also like