How to Determine Indentation: Converting Java Source FIle to HTML File - java

I'm trying to programatically convert a Java source file into an HTML file using PrintWriter to write to a seperate .html file
Example source file may look like this.
HelloWorld.java:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
while (true) {
System.out.println("Hello World!");
// Disregard this ridiculous example
}
}
}
All My printing works fine except I have a problem with indentation. Everyting is aligned left.
HelloWorld.html (as seen in browser):
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
while (true) {
System.out.println("Hello World!");
// Disregard this ridiculous example
}
}
}
Program Source Code Snippet: I want this program to determine for me, which line in the java source code should get indentation when it is being converted to HTML. I don't want to do it manually, because then I'd have to write a different program for every source file
PrintWriter output = new PrintWriter(newFile);
output.print("<!DOCTYPE html><html><head>"
+ "<style>"
+ ".keyword { font-weight: bold; color: blue}"
+ "</style></head><body>");
while (input.hasNextLine()) {
String line = input.nextLine();
String[] tokens = line.split(" ");
for (int i = 0; i < tokens.length; i++) {
if (keywordSet.contains(tokens[i])) {
// Gives Java keyword bold blue font
output.print("<span class=\"keyword\">");
output.print(tokens[i] + " ");
output.print("</span>");
} else {
output.print(tokens[i] + " ");
}
}
output.print("<br/>");
}
output.print("</body><html>");
output.close();
Note: The reason I split() each line is because certain keywords that may be in that line, are doing to be highlighted in the html file, which I do with a <span>, as noted in my code
In the program source code, I obviously don't have any indenting implementation, so I know why I don't have indentation in the html file. I really don't know how to go about implementing this.
How do I determine which line gets indentation, and how much indentation?
EDIT:
My Guess: Determine how much whitespace is in the line before splitting it, save the into a variable, then print those spaces in for form of &nbsp's before I print anything else in the line. But how do I determine how much whitespace is at the beginning of the line?

You can use a CSS class with white-space: pre or pre-line or pre-wrap.
You can wrap each line in a <p> with a calculated margin-left. It could be a multiple of 10px, for example. This would let you also change brace styles.
Basically, you'll have to keep a variable, indentLevel. Increment it for each { not in a string or a comment, and decrement it for each } not in a string or a comment. Indent each line, say 10px times the indent level. Test; do you want continuation lines indented more?

Use pre tag.
The tag defines preformatted text.
Text in a element is displayed in a fixed-width font (usually
Courier), and it preserves both spaces and line breaks.
You don't need to dermine which line needs to be indented because pre tag preserves ALL spaces, carriage returns and line feeds 'as-is' from the original HTML source code.
If you check the HTML that is rendered in StackOverflow in something marked as code you will see that it uses this tag.

Maybe it's better to first prepare String with your source code adding needed HTML, and replacing spaces with . This can be done with String.replace() method - iterate over you keywordSet and replace all keywords with its wrapped versions. Then you will able to write full string into your stream.

I figure out what I was trying to accomplish
...
int whiteSpace = 0;
while (whiteSpace < line.length() && Character.isWhitespace(line.charAt(j))) {
whiteSpace++;
}
String[] tokens = line.split(" ");
// Print white space
for (int i = 0; i < whiteSpace; i++) {
output.print("&nbsp");
}
...

Related

Java countdown print in same point of screen [duplicate]

I want to print a progress bar like so:
[# ] 1%
[## ] 10%
[########## ] 50%
But these should all be printed to the same line in the terminal instead of a new one.
What I mean by that is that each new line should replace the previous, it's not about using print() instead of println().
How can I do that in Java?
Format your string like so:
[# ] 1%\r
Note the \r character. It is the so-called carriage return that will move the cursor back to the beginning of the line.
Finally, make sure you use
System.out.print()
and not
System.out.println()
In Linux, there is different escape sequences for control terminal. For example, there is special escape sequence for erase whole line: \33[2K and for move cursor to previous line: \33[1A. So all you need is to print this every time you need to refresh the line. Here is the code which prints Line 1 (second variant):
System.out.println("Line 1 (first variant)");
System.out.print("\33[1A\33[2K");
System.out.println("Line 1 (second variant)");
There are codes for cursor navigation, clearing screen and so on.
I think there are some libraries which helps with it (ncurses?).
First, I'd like to apologize for bringing this question back up, but I felt that it could use another answer.
Derek Schultz is kind of correct. The '\b' character moves the printing cursor one character backwards, allowing you to overwrite the character that was printed there (it does not delete the entire line or even the character that was there unless you print new information on top). The following is an example of a progress bar using Java though it does not follow your format, it shows how to solve the core problem of overwriting characters (this has only been tested in Ubuntu 12.04 with Oracle's Java 7 on a 32-bit machine, but it should work on all Java systems):
public class BackSpaceCharacterTest
{
// the exception comes from the use of accessing the main thread
public static void main(String[] args) throws InterruptedException
{
/*
Notice the user of print as opposed to println:
the '\b' char cannot go over the new line char.
*/
System.out.print("Start[ ]");
System.out.flush(); // the flush method prints it to the screen
// 11 '\b' chars: 1 for the ']', the rest are for the spaces
System.out.print("\b\b\b\b\b\b\b\b\b\b\b");
System.out.flush();
Thread.sleep(500); // just to make it easy to see the changes
for(int i = 0; i < 10; i++)
{
System.out.print("."); //overwrites a space
System.out.flush();
Thread.sleep(100);
}
System.out.print("] Done\n"); //overwrites the ']' + adds chars
System.out.flush();
}
}
You could print the backspace character '\b' as many times as necessary to delete the line before printing the updated progress bar.
package org.surthi.tutorial.concurrency;
public class IncrementalPrintingSystem {
public static void main(String...args) {
new Thread(()-> {
int i = 0;
while(i++ < 100) {
System.out.print("[");
int j=0;
while(j++<i){
System.out.print("#");
}
while(j++<100){
System.out.print(" ");
}
System.out.print("] : "+ i+"%");
try {
Thread.sleep(1000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("\r");
}
}).start();
}
}
One could simply use \r to keep everything in the same line while erasing what was previously on that line.
In kotlin
print()
The print statement prints everything inside it onto the screen.
The print statements internally call System.out.print.
println()
The println statement appends a newline at the end of the output.
You can just do
System.out.print("String");
Instead
System.out.println("String");

How do I format this text? java

So here's the problem. Turn a text file into the correct formatting.
The point of the problem is that I have to read a file, a text file, which contains code in that text file. The code in that has terrible formatting. The formatting issue is that when there is a curly brace like this {, the next line is not 4 spaces to the right, it's just all to the very left. Like this:
while (blah blah blah) {
sysout(blahblahblah);
When it should be this:
while (blah blah blah) {
sysout(blahblahblah);
And there's no other differences between the 2. The only rule is to simply make it so every time there is a curly brace like this {, to make sure the next line is 4 spaces to the right. And vice versa. So every time there's a curly brace like this }, the next line should be 4 spaces to the left. I hope you guys understand this.
This is my issue. I learned how to make a program where a piece of text with multiple spaces and lines is turned into a single line with a single space every time. Wasn't too hard.
For this, though, I have to keep everything on the same line. So if there's 30 lines, the new program I make is also 30 lines. I need to keep very similar spacing, but the simple difference is the whole brace thing. So basically, I just have to make the line after a brace either 4 spaces to the right, and then do the same so it is to the left 4 spaces if it's a } curly brace.
So how do I do this exactly? I don't know how to just fix that without messing up other things. It's such a simple thing I have to do; just make the lines following the braces 4 spaces to the right or left, but I just have no idea what syntax to use to accomplish this. Thanks!
EDIT: This might have just made it easier. So, basically, all lines either end with a right curly brace, a left curly brace, or a semi-colon. No matter what. So every time one of those pops up, it is the end of a line. So maybe if you know how that makes it easier, then I'm just letting you know.
There are programs that will do this for you automatically, so you don't need to reinvent the wheel. For instance, in Eclipse, type: ctrl-a (select all) ctrl-i (auto-indent).
Here's a pseudocode you can start with:
int indentLevel = 0;
while(currentchar = nextchar != null){
printCurrentChar
if(currentchar is '{'){
indentLevel++;
}else if(currentchar is '}'){
indentLevel--;
}else if(currentchar is '\n'){
print indentLevel * 4 spaces
}
}
you might need to deal with escaped braces and other complications though
You can do this pretty easily using regular expressions. If you do not know it and planning to be a programmer, then definitely learn it. It will save for you lots of time in future.
public class TextIndentator
{
public static void main(String[] args) throws IOException
{
File uglyText = new File("ugly.txt");
System.out.println((uglyText.exists() && !uglyText.isDirectory()) ? getNiceText(uglyText) : "FILE \"ugly.txt\" at " + System.getProperty("user.dir") + " do not exists");
}
static String getNiceText(File uglyText) throws IOException
{
// Opening file
FileInputStream inputStream = new FileInputStream(uglyText);
InputStreamReader isr = new InputStreamReader(inputStream);
BufferedReader reader = new BufferedReader(isr);
StringBuilder builder = new StringBuilder();
StringBuffer buffer = new StringBuffer();
// Algorithm starts here
String line;
boolean checkNext = false;
while ((line = reader.readLine()) != null)
{
if(checkNext)
{
// If previous line finished with '{' (And optionally with some whitespaces after it) then, replace any amount (including zero) of whitespaces with 4 witespaces
builder.append(line.replaceFirst("\\s*", " "));
}
else
{
builder.append(line);
}
// Check if line line finishes with { (And optionally with some whitespaces after it)
if(line.matches(".*\\{\\s*")) checkNext = true;
else checkNext = false;
//Append line separator at the end of line
builder.append(System.getProperty("line.separator"));
}
return builder.toString();
}
}

Reliable saving JTextArea string in multi entry text file

I have a software that stores its data in multible nested data objects. On saving this project data, every instance gets an out handle (BufferedWriter) and writes its own data. Most data is single line and no problem, but there are a few multiline strings that come from JTextAreas. For storing them, I wrote a sub method multiLineWriter(), that splits the string in single lines, writes the number of lines and then the single lines. In theory. Because its not always working. Often it writes out the line count as 1 but then writes out two lines. Or it writes out 1, but writes out two lines with text and an empty line. Its not reliable. After loading the project back, often the complete data is destroyed. A typcal object saving block looks like this:
// *** write data to file
public void writeDataFile(BufferedWriter out) {
try {
out.write(""+getHeadline() );
out.newLine();
out.write(""+getStartDateAsString() );
out.newLine();
out.write(""+getEndDateAsString() );
out.newLine();
out.write(""+getPlaceIndex() );
out.newLine();
multiLineWriter(out, getDescription() );
} catch(Exception e) {}
}
// *** read data from File
public void readDataFile(BufferedReader in) {
try {
setHeadline(in.readLine());
setStartDateAsString(in.readLine());
setEndDateAsString(in.readLine());
setPlaceIndex(in.readLine());
setDescription(multiLineReader(in));
} catch(Exception e) {}
}
The multline writer/reader looks like this:
public void multiLineWriter(BufferedWriter out, String areaText) {
try {
String ls = System.getProperty("line.separator");
String[] lines = areaText.split(ls);
int lineCount = lines.length;
out.write(""+lineCount);
out.newLine();
for(int i = 0;i<lineCount;i++) {
out.write(lines[i]);
out.newLine();
}
} catch(Exception e) {}
}
public String multiLineReader(BufferedReader in) {
String targetString = "";
try {
String ls = System.getProperty("line.separator");
int lineCount = Integer.parseInt(in.readLine());
for(int i = 0;i<lineCount;i++) {
targetString = targetString + in.readLine() + ls;
}
} catch(Exception e) {}
return targetString;
}
As said, lineCount often is 1, but the loop seems to go two or more times because I have sometimes two or three lines after the 1 in a datafile.
This is not reliable for the project. Do you have an idea how I can change the multiLineWriter/reader to reliably store and read the data? The JTextArea save method does not work in this combined data file format.
__More info: __
Properties are a good style for the whole datafile. Since I was allright with the old style seen above most of the times I am sticking to that. Changing the current project to properties is a lot of handwork.
I reuse the out. I have Project Object, that creates the out. This out is then passed to multiple objects with subobjects, sometimes in loops, and everyone writes it data to this single out. After all data is written the project Object of course flushes and closes the stream. The empty exceptions are no problem in this case, because there are no exceptions (so there is nothing to analyse in a stack trace). Its not an exception problem but a logical problem.
The JTextArea read/write is not a good option. At time of saving the file, the data is not in a JTextArea but in a string, that was saved sometime ago during runtime from a JTextArea. To use the write method of JtextArea I would need to restore the string to the area and then use the write method. Because of hundreds of those description objects I would need to do this hundred of times in a save process. Sounds not well. On the other hand I am sure that the read method would not work, because it would read in the datafile up to the end and wouldn't handle the nested datastructure in the datafile.
Its not bad to be human readable. Currently this is helping me, to manually correct the values after a save process, so I am not loosing any data (I now this is stupid, but it works:-)
To be short: I guess I have a problem with the split method of strings and the content of the strings in the string array.
Problem should be made clearer. I have this JTextArea. It is like one field in a display for datasets (its a little private genealogy program that mainly manages hundreds of persons and places). A lot of dataobjects have a description field. Contents of the JTextArea are stored to one single String variable when you change the person in display for example (String personDescription). The writeDataFile() Method you see above is for an event object, that has a description field, too.
So when I write a File, I write from one String to the file. Since this string is taken from the JTextArea, it contains all new line characters that you can produce in a JTextArea. When storing this with one out.write (data) call you have multiple lines in the resulting data file because of possible new line characters in the String. So you can't read all this content back with one in.readLine() call. That's why I created the multiline writers and readers. But they don't work as expected.
Here I show you an exerpt from the resulting datafile
...
# +++ FileCollection:
0
# +++ ImageCollection:
0
58
true
Surname
Arthur
25.09.1877
1
01.01.1950
6
https://familysearch.org/
1
Bekannt ist, dass er auf dem Friedhof Großbeerenstr. lag.
Bekannt ist auch, dass die Trauzeugen bei der Heirat Dorothea Surname und Hermann Surname waren. Hermann ist vermutlich ein Bruder von Valerie.
Weitere Informationen gibt es nicht bisher.
# +++ EventCollection:
0
# +++ FileCollection:
0
...
There is more data before and below, but here is the wrong written data. Its directly below the link to familysearch.org. The first line that follows should have the line count. If there is no text it would have a 0 and the next line would be the info sting '# + EventCollection:'. If there would be one line, it would have a 1 and the next line would be that single line of text for description. Or other numbers depending on the amount of lines from the JTextArea. But as you see, there is written a 1 in this case, but there are 3 (!) Lines of text following.
So the main problem seems to be the way I work with the split method in the multiLineWriter().
String ls = System.getProperty("line.separator");
String[] lines = areaText.split(ls);
int lineCount = lines.length;
This seems to be critical. Since I write the resulting array of the split in a loop, this loop must be done three times? Because I have 3 lines of text in the datafile. But the lineCount is written as a 1? So this seems to be wrong. Could be that this string was not splitted, but still contains line break characters. That would not be what I am looking for. And in the array of splittet Strings there should not be any line break characters anymore (that would destroy the file writing, too).
Hope the problem is better described now. And the question is, how should the multiline writer and reader method be designed to store and read this data reliable.
I tried it myself. As I said there was a problem using the split method on strings. I changed this now to use a Scanner. To be correct, I use some ideas from How do I use System.getProperty("line.separator").toString()?
So in the end I just changed the multiLineWrite Method to use the Scanner (from the util package). It looks like this:
public void multiLineWriter(BufferedWriter out, String areaText) {
List<String> slines = new ArrayList<String>();
try {
Scanner sc = new Scanner(areaText);
while (sc.hasNextLine()) {
slines.add(sc.nextLine());
}
int slineCount = slines.size();
out.write(""+slineCount);
out.newLine();
for(int i = 0;i<slineCount;i++) {
out.write(slines.get(i));
out.newLine();
}
} catch(Exception e) {}
}
So now this seems to be reliable for me. I did a test with parallel writing of the split method and the Scanner method, and the split method had the wrong line count and the Scanner was correct.

How can I print to the same line?

I want to print a progress bar like so:
[# ] 1%
[## ] 10%
[########## ] 50%
But these should all be printed to the same line in the terminal instead of a new one.
What I mean by that is that each new line should replace the previous, it's not about using print() instead of println().
How can I do that in Java?
Format your string like so:
[# ] 1%\r
Note the \r character. It is the so-called carriage return that will move the cursor back to the beginning of the line.
Finally, make sure you use
System.out.print()
and not
System.out.println()
In Linux, there is different escape sequences for control terminal. For example, there is special escape sequence for erase whole line: \33[2K and for move cursor to previous line: \33[1A. So all you need is to print this every time you need to refresh the line. Here is the code which prints Line 1 (second variant):
System.out.println("Line 1 (first variant)");
System.out.print("\33[1A\33[2K");
System.out.println("Line 1 (second variant)");
There are codes for cursor navigation, clearing screen and so on.
I think there are some libraries which helps with it (ncurses?).
First, I'd like to apologize for bringing this question back up, but I felt that it could use another answer.
Derek Schultz is kind of correct. The '\b' character moves the printing cursor one character backwards, allowing you to overwrite the character that was printed there (it does not delete the entire line or even the character that was there unless you print new information on top). The following is an example of a progress bar using Java though it does not follow your format, it shows how to solve the core problem of overwriting characters (this has only been tested in Ubuntu 12.04 with Oracle's Java 7 on a 32-bit machine, but it should work on all Java systems):
public class BackSpaceCharacterTest
{
// the exception comes from the use of accessing the main thread
public static void main(String[] args) throws InterruptedException
{
/*
Notice the user of print as opposed to println:
the '\b' char cannot go over the new line char.
*/
System.out.print("Start[ ]");
System.out.flush(); // the flush method prints it to the screen
// 11 '\b' chars: 1 for the ']', the rest are for the spaces
System.out.print("\b\b\b\b\b\b\b\b\b\b\b");
System.out.flush();
Thread.sleep(500); // just to make it easy to see the changes
for(int i = 0; i < 10; i++)
{
System.out.print("."); //overwrites a space
System.out.flush();
Thread.sleep(100);
}
System.out.print("] Done\n"); //overwrites the ']' + adds chars
System.out.flush();
}
}
You could print the backspace character '\b' as many times as necessary to delete the line before printing the updated progress bar.
package org.surthi.tutorial.concurrency;
public class IncrementalPrintingSystem {
public static void main(String...args) {
new Thread(()-> {
int i = 0;
while(i++ < 100) {
System.out.print("[");
int j=0;
while(j++<i){
System.out.print("#");
}
while(j++<100){
System.out.print(" ");
}
System.out.print("] : "+ i+"%");
try {
Thread.sleep(1000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("\r");
}
}).start();
}
}
One could simply use \r to keep everything in the same line while erasing what was previously on that line.
In kotlin
print()
The print statement prints everything inside it onto the screen.
The print statements internally call System.out.print.
println()
The println statement appends a newline at the end of the output.
You can just do
System.out.print("String");
Instead
System.out.println("String");

Writing to File in Java: output displays differently in NotePad vs. Word/WordPad/NotePad++

Below is the Java code for reading an existing text file called Sales.txt
and outputting a bar chart to a text file called storeReport.txt
Each asterisk represents $100 in sales.
import java.io.*;
import java.util.*;
public class BarChart
{
public static void main(String[] args) throws FileNotFoundException, IOException
{
int[] s = new int[5];
int[] b = new int[5];
FileWriter fstream = new FileWriter("storeReport.txt");
BufferedWriter out = new BufferedWriter(fstream);
Scanner scanner = new Scanner(new File("Sales.txt"));
int i = 0;
while(scanner.hasNext())
s[i++] = scanner.nextInt();
System.out.println("SALES BAR CHART\n");
out.write("SALES BAR CHART\n");
for (i=0; i<s.length; i++)
{
b[i] = s[i]/100;
out.write("store "+ (i+1) +" : ");
System.out.print("store "+ (i+1) +" : ");
for(int j = 1; j <= b[i]; j++) {
System.out.print("*");
out.write("*"); }
out.write("\n");
System.out.println();
}
out.close(); //Close the output stream
}
}
When I open storeReport.txt in Word, or WordPad, or NotePad++ the output is displayed as was intended:
store 1 : ***
store 2 : *****
store 3 : ********
store 4 : **
store 5 : *********
When I open the file in NotePad, the outputs are displayed all on one line. (I'm using Windows 7 and the latest jGrasp to compile and run the program.)SALES BAR CHART
The input file Sales.txt reads as such:
1000
1200
1800
800
1900
Anybody have an idea on why NotePad shows the output as:
SALES BAR CHARTstore 1 : ***store 2 : ****store 3 : ********store 4 : **store 5 : **********
I suspect this is a newline issue. Try replacing your
out.write("\n");
with
out.newLine();
Notepad does not interpret a simple Newline '\n' character as a newline. It uses the "Windows" format of Carriage Return + Newline "\r\n" to designate a newline.
You'll basically need to do one of the following:
Stop using Notepad
Use some program to convert the line-end characters to CR+LF (unix2dos)
Change your program to output \r\n
I think most people would agree that #1 is your best choice, but I don't really know a lot about how far the \r\n problem extends on windows platforms.
Edit: As srgerg noted in his answer, your best option is to stop specifying \n on your own and use JAVA's out.newLine() function to produce line ends. These will be correct for whatever platform you use.
See Wikipedia for more information:
http://en.wikipedia.org/wiki/Newline#Common_problems
Notepad only understands DOS/Windows line endings, which is \r\n, while Notepad++ and Wordpad handle Linux/Unix/new MacOS (\n) and older MacOS (\r) line endings as well.
You can try to get the right line end for your system:
System.getProperty ("line.separator");
Or try to use println () or printf/format in combination with "%n", and the program will do what is appropriate on the running platform.
Installing a more elaborated editor than notepad isn't a bad idea, though.
I agree with the other answers provided above. Just a little design pointer which might enhance the overall thinking.
What I understood is you are creating some data and then trying to generate some graph out of it....
How about using a explicit field separator and record separator.
Use some encoding. This will provide you better control if this is run in different environments.

Categories