As a programmer we should always make sure our program is easily readable and understandable by other programming fellows. A program can be easily followed only when it is formatted properly i.e.; with proper indentation, with different coloring for keywords, string literals etc.

I've implemented a Java program to format the code which can be shared on the web. i.e; my program will apply a HTML element with class name (for eg, keywords will be applied a style with <span class="keyword">) for each type of programming element.

All the programs that are posted on my blog uses this program. Please note that indentation hasn't been implemented yet. I shall update again when I implement that. This program output will be generated as an HTML file with all the styles applied.

Every IDE will execute a program something similar to this when you request IDE to reformat your program.

FormatProgramV2.java
import java.io.FileReader;
import java.io.File;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.util.Stack;

/**
* This class formats a given Java program.
* @author SANTHOSH REDDY MANDADI
* @version 1.0
* @since 03-October-2012
*/
public class FormatProgramV2
{
public static void main(String args[]) throws Exception
{
String fileName = "";
//Checking for the file name through command line argument
if(args!=null && args.length>0)
{
fileName = args[0];
}
else
{
System.out.println("Please input a Java program file name as below:");
System.out.println("java FormatProgramV2 Example.java");
return;
}

//Exiting program execution if the file is not of Java
if(!fileName.endsWith(".java"))
{
System.out.println("Sorry, this program can format only Java programs.");
return;
}

if(!(new File(fileName).exists()))
{
System.out.println("File not found - "+fileName);
return;
}

//Opening file input stream
FileReader fileReader = new FileReader(fileName);
BufferedReader reader = new BufferedReader(fileReader);

//Creating a new file .html to generate output
FileWriter fileWriter = new FileWriter(fileName.replaceAll("\\.java", ".html"));
BufferedWriter writer = new BufferedWriter(fileWriter);

//Reserved words list to apply a keyword class
String reservedWords[] = {"class", "abstract", "assert", "boolean", "break",
"byte", "case", "catch", "char", "const", "continue",
"default", "do", "double", "else", "enum", "extends",
"final", "finally", "float", "for", "goto", "if",
"implements", "import", "instanceof", "int", "interface",
"long", "native", "new", "package", "private",
"protected", "public", "return", "short", "static",
"strictfp", "super", "switch", "synchronized", "this",
"throw", "throws", "transient", "try", "void",
"volatile", "while"
};
//String to hold the entire program
String program = "";
//String to hold the generate HTML source
StringBuffer html;
//Temporary variable to read content from file
String str = "";

//Flag to hold whether doubleQuote started
boolean doubleQuote = false;
//Flag to hold whether singleQuote started
boolean singleQuote = false;
//Flag to hold whether multiLineComment started
boolean multiLineComment = false;
//Flag to hold whether keyword started
boolean word = false;
//Flag to hold whether singleLineComment started
boolean singleLineComment = false;
//Flag represent any of the above tokens started
boolean flag = false;

int commentPosition = -1;
while(str!=null)
{
str = reader.readLine();
if(str!=null)
{
program += str+"\n";
}
}
program = program.replaceAll("<", "<");
program = program.replaceAll(">", ">");
html = new StringBuffer(program);
char prevChar = ' ';
char secondPrevChar = ' ';
int programPosition=0;
int htmlPosition = 0;
String keyword = "";

try
{
for(char ch: program.toCharArray())
{
if(Character.isLetterOrDigit(ch))
{
keyword += ch;
word = true;
}
else
{
if(ch=='"' && ((secondPrevChar=='\\' && prevChar=='\\') || prevChar!='\\' ) &&!singleQuote)
{
//Ending double quote
if(doubleQuote)
{
html.insert(htmlPosition+1, "</span>");
htmlPosition += "</span>".length();
doubleQuote = false;
}
else
{
//Inserting double quote
html.insert(htmlPosition, "<span class=\"str\">");
htmlPosition += "<span class=\"str\">".length();
doubleQuote = true;
}
}
else if(ch=='\'' && ((secondPrevChar=='\\' && prevChar=='\\') || prevChar!='\\' ) &&!doubleQuote)
{
if(singleQuote)
{
//Ending single quote
html.insert(htmlPosition+1, "</span>");
htmlPosition += "</span>".length();
singleQuote = false;
}
else
{
//Inserting singel quote
html.insert(htmlPosition, "<span class=\"char\">");
htmlPosition += "<span class=\"char\">".length();
singleQuote = true;
}
}
else if(ch=='/' && html.charAt(htmlPosition+1)=='*' && !multiLineComment && !doubleQuote) /*/*******/
{
//Inserting a comment
html.insert(htmlPosition, "<span class=\"comment\">");
htmlPosition += "<span class=\"comment\">".length();
multiLineComment = true;
commentPosition = programPosition;
}
else if(ch=='/' && prevChar == '*' && programPosition>commentPosition+2)
{
//Ending a comment
html.insert(htmlPosition+2, "</span>");
htmlPosition += "</span>".length();
multiLineComment = false;
commentPosition = -1;
}
else if(ch=='/' && html.charAt(htmlPosition+1)=='/' && !singleLineComment && !doubleQuote)
{
//Inserting a comment
html.insert(htmlPosition, "<span class=\"comment\">");
htmlPosition += "<span class=\"comment\">".length();
singleLineComment = true;
}
else if((ch=='\r' || ch=='\n') && singleLineComment) ////Comments....
{
//Ending a comment
html.insert(htmlPosition+2, "</span>");
htmlPosition += "</span>".length();
singleLineComment = false;
}

if(!doubleQuote && !singleQuote && !singleLineComment && !multiLineComment)
{
word = false;
if(!keyword.equals(""))
{
for(String s:reservedWords)
{
if(s.equals(keyword))
{
//Inserting keyword
html.insert(htmlPosition-keyword.length(), "<span class=\"word\">");
htmlPosition += ("<span class=\"word\">".length());
//Ending keyword
html.insert(htmlPosition, "</span>");
htmlPosition += ("</span>".length());
}
}
}
keyword = "";
}
}
secondPrevChar = prevChar;
prevChar = ch;
programPosition++;
htmlPosition++;
}
}
finally
{
html.insert(0,"<style type=\"text/css\">\n"+
" .program {\n"+
" font: 400 13px Roboto,sans-serif;\n"+
" border-radius: 10px;\n"+
" line-height: 1.5em;\n"+
" overflow: auto;\n"+
" background-color: #f0f0f0;\n"+
" color: black;\n"+
" margin: 3px 0;\n"+
" padding: 10px 0 5px 10px;\n"+
" }\n"+
" .word{\n"+
" color: #008;\n"+
" }\n"+
" .str {\n"+
" color: #080;\n"+
" }\n"+
" .char {\n"+
" color: #080;\n"+
" }\n"+
" .comment{\n"+
" color: #333;\n"+
" }\n"+
"</style><pre class=\"program\">");
writer.write(html.toString()+"</pre>");
writer.close();
fileWriter.close();
reader.close();
fileReader.close();
System.out.println("Generated a formatted source file - "+fileName.replaceAll("\\.java", ".html"));
}
}
}
Explanation

Java program file should be passed as a command line argument. I've handled below scenarios to detect the input

  • The file should definitely be a Java program
  • File should exist on the disk
A HTML file will be generated with <<file name>>.html by formatting the program.

Output
santhosh> java FormatProgramV2
Please input a Java program file name as below:
java FormatProgramV2 Example.java

santhosh> java FormatProgramV2 Example.java
File not found - Example.java

santhosh> java FormatProgramV2 Notepad.java
Generated a formatted source file - Notepad.html

If you've sometime, why don't you checkout my other Java programs