Write string to a specific position in file - java

I am using BufferedWriter to write strings to a file like this:
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
String myname = "JOHN DOE MAXWELL";
String myotherName = "MELCHIZEDEK NEBUCHARDINEZZAR";
String mylocation = "SOUTH EAST";
String myotherlocation = "SOUTH WEST";
File f = new File("MyFile.txt");
BufferedWriter bw = new BufferedWriter(new FileWriter(f));
bw.write(myname + " " + mylocation);
bw.newLine();
bw.write(myothername + " " + myotherlocation);
bw.close();
}
}
I need to write mylocation such that whatever the length of the string myname, the beginning position of mylocation will not be affected. Please assist.
My Outputshould be:
JOHN DOE MAXWELL SOUTH EAST
MELCHIZEDEK NEBUCHARDI SOUTH WEST

You could do
bw.write(String.format("%-20s%s%n", myName, myLocation));
You can use PrintWriter to use printf() which does both.
e.g. Using PrintWriter
pw.printf("%-" + myNameWidth + "s%s%n", myName, myLocation);

try this
bw.write(myname + " ".substring(0, 30) + " " + mylocation);

Using Google Guava:
Strings.padEnd("JOHN DOE MAXWELL", 26, ' ').length()
String will be always 26 characters length.

such that whatever the length of the string myname, the beginning
position of mylocation will not be affected
The only case i can think of is when each one is in a new line.
You must specify the maximum tolerted length after which this order is no longer guaranteed, the formating actually should occur on reading the file, at that point you can determine the longest variable of myname and format your output according to it.

Related

Appending in Serialization

So far I have found that there is a way to do appending in serialization by making a sub-class but that seems like a lengthy way. Is there any better way to do appending in serialization?
I have this vectorlist in a class named Course
private Vector<Student> StudentList = new Vector<>();
I have 2 objects of course.
3 students are enrolled in 1 course and 2 students are enrolled in another. Now I call this method which is doing serialization in the file but when I call it with my 2nd course object, it replaces previous content.
public void Serialization() {
try {
File file = new File("EnrolledStudentsSerial.txt");
if(!file.exists()){
file.createNewFile();
}
FileOutputStream fo = new FileOutputStream(file);
ObjectOutputStream output = new ObjectOutputStream(fo);
output.writeObject("Course: " + this.name + "\n\nEnrolled Students: ");
for (int i = 0; i < StudentList.size(); i++) {
Student p_obj = StudentList.elementAt(i);
String content = "\n\tStudent Name: " + p_obj.getName() + "\n\tStudent Department: " + p_obj.getDepartment() + "\n\tStudent Age: " + p_obj.getAge() + "\n";
output.writeObject(content);
}
output.writeObject("\n");
fo.close();
} catch (IOException ioe){
System.out.println("Error: " + ioe.getMessage());
}
}
If you want to append to a file, instead of replacing the content, you need to tell the FileOutputStream that, by adding an extra argument and call FileOutputStream(File file, boolean append). FYI: don't do that with an ObjectOutputStream.
You don't need to call createNewFile(), since FileOutputStream will do that, whether appending or not.
However, you are not actually serializing your objects, since you're serializing strings instead. What you're doing makes no sense. Since you seem to want the result to be a text file (you're writing text, and file is names .txt), you should forget about ObjectOutputStream, and use a FileWriter instead.
Better yet, instead of using the old File I/O API, you should be using the "newer" NIO.2 API that was added in Java 7. You should also be using try-with-resources. Same goes for the ancient Vector class, which was replaced by ArrayList in Java 1.2.
Java naming convention is for field and method names to start with lowercase letter. And since your method is not "serializing" anymore, you should give it a better name.
Applying all that, your code should be:
import static java.nio.file.StandardOpenOption.APPEND;
import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.WRITE;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
private ArrayList<Student> studentList = new ArrayList<>();
public void writeToFile() {
Path file = Paths.get("EnrolledStudentsSerial.txt");
try (BufferedWriter output = Files.newBufferedWriter(file, CREATE, APPEND, WRITE)) {
output.write("Course: " + this.name + "\n\nEnrolled Students: ");
for (Student student : studentList) {
String content = "\n\tStudent Name: " + student.getName() +
"\n\tStudent Department: " + student.getDepartment() +
"\n\tStudent Age: " + student.getAge() + "\n";
output.write(content);
}
output.write("\n");
} catch (IOException ioe){
System.out.println("Error: " + ioe.getMessage());
}
}

javax.swing.UIManager.getIcon(Object key) returns null when String-keys are streamed from an ArrayList

What I want to achieve:
I want to visualize some javax.swing.Icons from the javax.swing.UIManager. On the internet I've found a list of UIManager-keys, which will not only return Icons but also Strings, Colors and so on. So in this step I want to filter the list of keys so only the Icon-keys remain.
My Approach:
I copied a list of UIManager keys into a textfile and included it as recource in my Java-Project. I successfully read the file so I split the file-content by lines and added them to an ArrayList of Strings. Now i wanted to stream the content of this ArrayList and filter the keys by wether the UIManager.getIcon(Object key)-Method returns null or not...
My Problem
so far: the UIManager always returns null. I printed all the keys and the UIManager result to the console (see "Output / Test - stream keys" in my code). If i manually copy a key from the console (one that I know should work) and paste it into the exact same piece of code, it actually works (see "Output / Test - single Key" in my code).
Interesting Behavior shows when I append a String to the key that I want to print to the console (See the variable "suffix" under "Output / Test - stream Keys" in my code). If the variable suffix does not start with "\n", the following print-Method in the stream will only print the suffix and no longer show the other content. For example if I type String suffix = "test"; only "test" will be printed from the .forEach(key->System.out.println(... + key + suffix); However, this behavior does not show up in the "Output / Test - single Key"-Example.
I have no idea, what is going on or if the (in my opinion) strange behavior as anything to do with the problem. I appreciate any kind of help!
Piece from "UIManagerKeys.txt":
Here are some keys for testing and reproducibility purposes...
FileView.computerIcon
FileView.directoryIcon
FileView.fileIcon
FileView.floppyDriveIcon
FileView.hardDriveIcon
FormattedTextField.background
FormattedTextField.border
windowText
My Code:
package main;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.UIManager;
public class Main {
public Main() {
}
public static void main(String args[]) {
ArrayList<String> uiKeys = new ArrayList<>();
String fileName = "recources/UIManagerKeys.txt";
ClassLoader classLoader = new Main().getClass().getClassLoader();
File file = new File(classLoader.getResource(fileName).getFile());
// Check: is File found?
System.out.println("File Found : " + file.exists());
try {
// Read File Content
String content = new String(Files.readAllBytes(file.toPath()));
// Split by line and collect
String[] keys = content.split("\n");
uiKeys.addAll(Arrays.asList(keys));
} catch (IOException e) {
System.out.println("Error: " + e);
}
// Output / Test - stream Keys
System.out.println("Total Number of Keys: " + uiKeys.size());
String suffix = ""; // Interesting behavior when String is not empty
uiKeys.stream()
.map(key -> key.replaceAll(" ", "").replaceAll("\n", "")) // Just to be sure
.forEach(key -> System.out.println("IconFound: " + (UIManager.getIcon(key) != null) + "\tKey: " + key + suffix));
// Output / Test - single Key
System.out.println("\n");
String key = "FileView.directoryIcon"; // Copied from console
System.out.println("IconFound: " + (UIManager.getIcon(key) != null) + "\tKey: " + key + suffix);
}
}
I want to visualize some javax.swing.Icons from the javax.swing.UIManager.
I copied a list of UIManager keys into a textfile
There is no need to create the text file. You just get all the properties from the UIManager and check if the Object is an Icon:
public static void main(String[] args) throws Exception
{
UIDefaults defaults = UIManager.getLookAndFeelDefaults();
for ( Enumeration enumm = defaults.keys(); enumm.hasMoreElements(); )
{
Object key = enumm.nextElement();
Object value = defaults.get( key );
if (value instanceof Icon)
System.out.println( key );
}
}
On the internet I've found a list of UIManager-keys,
Check out: UIManager Defaults for a little graphical tool that displays all the properties.
Your approach of reading the files seems a little complicated. Here is a simple approach to reading the lines of a file into a ListArray:
import java.io.*;
import java.util.*;
public class ReadFile
{
public static void main(String [] args) throws Exception
{
ArrayList<String> lines = new ArrayList<String>();
BufferedReader in = new BufferedReader( new FileReader( "ReadFile.java" ) );
String line;
while((line = in.readLine()) != null)
{
lines.add(line);
}
in.close();
System.out.println(lines.size() + " lines read");
}
}

Why is this code for making a file from user input using the Scanner class not working?

My code is used to create a file inside a folder of a directory, with the file containing a heading at the top based on what the user inputs.
import java.util.*;
import java.text.*;
import java.io.*;
public class setup {
public static void main(String[] args) {
Scanner userin = new Scanner(System.in);
int hwnum;
String hwsummary;
int period;
String name;
System.out.println("Enter name: ");
name = userin.next();
System.out.println("Enter APCS period: ");
period = userin.nextInt();
System.out.print("Enter HW number: ");
hwnum = userin.nextInt();
System.out.println("Enter HW summary: ");
hwsummary = userin.next();
System.out.println("Enter file name: ");
String hwname = userin.next();
hwname = hwname + ".java";
new File("/hw" + hwnum).mkdirs();
new File("/hw" + hwnum +"/" + hwname);
String filename;
filename = "\\hw" + hwnum + "\\" + hwname;
System.out.println("/*");
System.out.println(name);
System.out.println("APCS1 " + "pd" + period);
System.out.println("HW" + hwnum + " -- " + hwsummary);
System.out.println(getdate());
System.out.println("*/");
}
public static String getdate() {
DateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");
Date date = new Date();
String todaydate;
todaydate = dateformat.format(date);
return todaydate;
}
}
The end result of the code, if give by the user should be a java file in a directory named "/hwxx" and should have a heading similar to:
/*
Name
APCS1 pdx
HW# - HWSUMMARY
DATE
*/
System.out.println() can't be used to write to a file, only to print text to the standard output stream. A FileWriter and BufferedWriter can be used instead to write to a file. Try replacing the last part of your main method with this:
try {
FileWriter outputStream = new FileWriter(filename);
try (BufferedWriter out = new BufferedWriter(outputStream)) {
out.write("/*");
out.newLine();
out.write(name);
out.newLine();
out.write("APCS1 pd" + period);
out.newLine();
out.write("HW" + hwnum + " -- " + hwsummary);
out.newLine();
out.write(getdate());
out.newLine();
out.write("*/");
}
} catch (IOException ex) {
// some sort of error message here
// this block will only be run if the program is unable to create or write to the specified file
}
Note that the write() method is the file-writing equivalent to print() rather than println(), so it's necessary to include the newline() method between each line of text to avoid having it all be written to the same line of text. However, a shorter and less tedious alternative is to add the string "\n" (newline) to the end of each line written to the file, like this:
out.write("/*\n");
out.write(name + "\n");
//etc.
If you choose to do it this way and it ends up writing all the text to a single line anyway (a common problem if you're running Windows), use "\r\n" instead of just "\n".

Remove a character followed by whitespace each newline of a string

I am writing a program to edit a rtf file. The rtf file will always come in the same format with
Q XXXXXXXXXXXX
A YYYYYYYYYYYY
Q XXXXXXXXXXXX
A YYYYYYYYYYYY
I want to remove the Q / A + whitespace and leave just the X's and Y's on each line. My first idea is to split the string into a new string for each line and edit it from there using str.split like so:
private void countLines(String str){
String[] lines = str.split("\r\n|\r|\n");
linesInDoc = lines;
}
From here my idea is to take each even array value and get rid of Q + whitespace and take each odd array value and get rid of A + whitespace. Is there a better way to do this? Note: The first line somteimes contains a ~6 digit alphanumeric. I tihnk an if statement for a 2 non whitespace chars would solve this.
Here is the rest of the code:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import javax.swing.JEditorPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.EditorKit;
public class StringEditing {
String[] linesInDoc;
private String readRTF(File file){
String documentText = "";
try{
JEditorPane p = new JEditorPane();
p.setContentType("text/rtf");
EditorKit rtfKit = p.getEditorKitForContentType("text/rtf");
rtfKit.read(new FileReader(file), p.getDocument(), 0);
rtfKit = null;
EditorKit txtKit = p.getEditorKitForContentType("text/plain");
Writer writer = new StringWriter();
txtKit.write(writer, p.getDocument(), 0, p.getDocument().getLength());
documentText = writer.toString();
}
catch( FileNotFoundException e )
{
System.out.println( "File not found" );
}
catch( IOException e )
{
System.out.println( "I/O error" );
}
catch( BadLocationException e )
{
}
return documentText;
}
public void editDocument(File file){
String plaintext = readRTF(file);
System.out.println(plaintext);
fixString(plaintext);
System.out.println(plaintext);
}
Unless I'm missing something, you could use String.substring(int) like
String lines = "Q XXXXXXXXXXXX\n" //
+ "A YYYYYYYYYYYY\n" //
+ "Q XXXXXXXXXXXX\n" //
+ "A YYYYYYYYYYYY\n";
for (String line : lines.split("\n")) {
System.out.println(line.substring(6));
}
Output is
XXXXXXXXXXXX
YYYYYYYYYYYY
XXXXXXXXXXXX
YYYYYYYYYYYY
If your format should be more general, you might prefer
System.out.println(line.substring(1).trim());
A BufferedReader will handle the newline \n for you.
You can use a matcher to validate that the line is in the desired format.
If the line is fixed length, simply use the substring
final String bodyPattern = "\\w{1,1}[ \\w]{5,5}\\d{12,12}";
try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
String line;
while ((line = br.readLine()) != null) {
if (line.matches(bodyPattern)) {
//
myString = line.substring(6);
}
}
}
//catch Block
You can adjust the regex pattern to your specific requirements
easily doable by a regex (assuming 'fileText' is your whole file's content)
removedPrefix = fileText.replaceAll("(A|Q) *(.+)\\r", "$2\\r");
The regex means a Q or A for start, then some (any amount of) spaces, then anything (marked as group 2), and a closing line. This doesn't do anything to the first line with the digits. The result is the file content without the Q/A and the spaces. There are easier ways if you know the exact number of spaces before your needed text, but this works for all, and greatly flexible.
If you process line by line it's
removedPrefix = currentLine.replaceAll("(A|Q) *(.+)", "$2");
As simple as that

runtime.exec with spaces in the parameters

I want to execute bash commands (on a Linux system) from Java.
The command I want to execute is:
/usr/bin/convert -pointsize 24 label:'Just a test.' ./dummy.png
I first used:
runtime.exec("/usr/bin/convert -pointsize 24 label:'Just a test.' ./dummy.png");
This worked, but used "Just" as a label instead of: "Just a test.". I now use:
runtime.exec(new String []{"/usr/bin/convert", "-pointsize 24", "label:'Just a test.'", "./dummy.png"});
This does not give an error, but there is no dummy.png generated.
How could I get this to work?
-- Edit:
With the help of MadProgrammer I solved the problem. I thought it a good idea to show a working example:
import java.util.Scanner;
import java.io.*;
public class SystemCommand {
// public #########################
public static void main(String[] args) {
try {
doCommand(new String[] {"/usr/bin/convert",
"-background", BACKGROUND,
"-fill", FILL,
"-font", FONT,
"-pointsize", FONTSIZE,
"label:" + CITATION,
FILENAME});
}
catch (IOException e) {
System.out.println(e.getMessage());
}
}
// private ########################
final static String INDENT = " ";
final static String AUTHOR = "Bruce Lee";
final static String BACKGROUND = "NavyBlue";
final static String CITATION =
"\n" +
INDENT + "We all have time to either spend or waste" + INDENT + "\n" +
INDENT + "and it is our decision what to do with it." + INDENT + "\n" +
INDENT + "But once passed, it is gone forever." + INDENT + "\n" +
"\n" +
INDENT + AUTHOR + INDENT + "\n";
final static String FILENAME = "citation.png";
final static String FILL = "Yellow";
final static String FONT = "Bookman-DemiItalic";
final static String FONTSIZE = "24";
static Runtime runtime = Runtime.getRuntime();
private static void doCommand(final String[] cmd) throws IOException {
int i;
Process p;
Scanner sc;
p = runtime.exec(cmd);
sc = new Scanner(p.getInputStream());
while (sc.hasNext()) {
System.out.println(sc.nextLine());
}
}
}
To test it in Linux (Image Magick has to be installed):
javac SystemCommand.java && java SystemCommand && display citation.png
When I made an example with ProcessBuilder I will add it here also.
-- Edit
The ProcessBuilder variant. In this case it is not very useful, but when you do something more complex, it will be a better solution.
/*
I needed to write some code that executes something in the Bash shell.
This is not to difficult, but when there are spaces, things can become difficult.
But if you know how it works, then there is no problem.
It can be done Runtime.getRuntime().exec. In this example that would be good enough.
(See SystemCommand.java) But when you have a little bit more difficult things to do,
it is better to use ProcessBuilder. That I do in this example.
The solution is: create a String array in which the first entry is the command
and every parameter has his own entry (without quoutes).
This program is the equavelent of:
/usr/bin/convert -background "NavyBlue" -fill "Yellow" -font "Bookman-DemiItalic" -pointsize 24 label:"
I hope I shall always possess
firmness and virtue enough
to maintain
what I consider the most
enviable of all titles,
the character of an honest man.
George Washington" citation.png
To test it:
javac SystemCommandWithProcessBuilder.java && \
java SystemCommandWithProcessBuilder && \
display citation.png
To use this you need of-course Java, but besides that ImageMagick needs to be installed.
It is written for Linux.
*/
import java.io.*;
public class SystemCommandWithProcessBuilder {
// public #########################
public static void main(String[] args) {
try {
doCommand(new String[] {"/usr/bin/convert",
"-background", BACKGROUND,
"-fill", FILL,
"-font", FONT,
"-pointsize", FONTSIZE,
"label:" + CITATION,
FILENAME});
}
catch (IOException e) {
System.out.println(e.getMessage());
}
}
// private ########################
final static String INDENT = " ";
final static String AUTHOR = "George Washington";
final static String BACKGROUND = "NavyBlue";
final static String CITATION =
"\n" +
INDENT + "I hope I shall always possess" + INDENT + "\n" +
INDENT + "firmness and virtue enough" + INDENT + "\n" +
INDENT + "to maintain" + INDENT + "\n" +
INDENT + "what I consider the most" + INDENT + "\n" +
INDENT + "enviable of all titles," + INDENT + "\n" +
INDENT + "the character of an honest man." + INDENT + "\n" +
"\n" +
INDENT + AUTHOR + INDENT + "\n";
final static String FILENAME = "citation.png";
final static String FILL = "Yellow";
final static String FONT = "Bookman-DemiItalic";
final static String FONTSIZE = "24";
private static void doCommand(final String[] cmd) throws IOException {
BufferedReader br;
String line;
Process p;
p = new ProcessBuilder(cmd).start();
br = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
To test it in Linux (Image Magick has to be installed):
javac SystemCommandWithProcessBuilder.java && \
java SystemCommandWithProcessBuilder && \
display citation.png
I have published both at: https://github.com/CecilWesterhof/JavaExamples
First of all, use ProcessBuilder it simplerfies the over all process
Having said that, each element in the String array is considered an individual parameter to the command, that is, this is exactly how the commands args[] array will look.
You could try something like...
runtime.exec(new String []{"/usr/bin/convert", "-pointsize", "24", "label:'Just a test.'", "./dummy.png"})

Categories