It has recently come to my attention that Java text components use line feed characters (LF, \n, 0x0A) to represent and interpret line breaks internally. This came as quite a surprise to me and puts my assumption, that using System.getProperty('line.separator') everywhere is a good practice, under a question mark.
It would appear that whenever you are dealing with a text component you should be very careful when using the mentioned property, since if you use JTextComponent.setText(String) you might end up with a component that contains invisible newlines (CRs for example). This might not seem that important, unless the content of the text component can be saved to a file. If you save and open the text to a file using the methods that are provided by all text components, your hidden newlines suddenly materialize in the component upon the file being re-opened. The reason for that seems to be that JTextComponent.read(...) method does the normalization.
So why doesn't JTextComponent.setText(String) normalize line endings? Or any other method that allows text to be modified within a text component for that matter? Is using System.getProperty('line.separator') a good practice when dealing with text components? Is it a good practice at all?
Some code to put this question into perspective:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class TextAreaTest extends JFrame {
private JTextArea jtaInput;
private JScrollPane jscpInput;
private JButton jbSaveAndReopen;
public TextAreaTest() {
super();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("Text Area Test");
GridBagLayout layout = new GridBagLayout();
setLayout(layout);
jtaInput = new JTextArea();
jtaInput.setText("Some text followed by a windows newline\r\n"
+ "and some more text.");
jscpInput = new JScrollPane(jtaInput);
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = 0; constraints.gridy = 0;
constraints.gridwidth = 2;
constraints.weightx = 1.0; constraints.weighty = 1.0;
constraints.fill = GridBagConstraints.BOTH;
add(jscpInput, constraints);
jbSaveAndReopen = new JButton(new SaveAndReopenAction());
constraints = new GridBagConstraints();
constraints.gridx = 1; constraints.gridy = 1;
constraints.anchor = GridBagConstraints.EAST;
constraints.insets = new Insets(5, 0, 2, 2);
add(jbSaveAndReopen, constraints);
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TextAreaTest tat = new TextAreaTest();
tat.setVisible(true);
}
});
}
private class SaveAndReopenAction extends AbstractAction {
private File file = new File("text-area-test.txt");
public SaveAndReopenAction() {
super("Save and Re-open");
}
private void saveToFile()
throws UnsupportedEncodingException, FileNotFoundException,
IOException {
Writer writer = null;
try {
writer = new OutputStreamWriter(
new FileOutputStream(file), "UTF-8");
TextAreaTest.this.jtaInput.write(writer);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException ex) {
}
}
}
}
private void openFile()
throws UnsupportedEncodingException, IOException {
Reader reader = null;
try {
reader = new InputStreamReader(
new FileInputStream(file), "UTF-8");
TextAreaTest.this.jtaInput.read(reader, file);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ex) {
}
}
}
}
public void actionPerformed(ActionEvent e) {
Throwable exc = null;
try {
saveToFile();
openFile();
} catch (UnsupportedEncodingException ex) {
exc = ex;
} catch (FileNotFoundException ex) {
exc = ex;
} catch (IOException ex) {
exc = ex;
}
if (exc != null) {
JOptionPane.showConfirmDialog(
TextAreaTest.this, exc.getMessage(), "An error occured",
JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE);
}
}
}
}
An example of what this program saves on my windows machine after adding a new line of text (why the single CR? o_O):
Edit01
I ran/debugged this from within Netbeans IDE, which uses JDK1.7u15 64bit (C:\Program Files\Java\jdk1.7.0_15) on Windows 7.
First of all, the real answer is that this is how the designers thought the design should work. You'd really need to ask them to get the real reason(s).
Having said that:
So why doesn't JTextComponent.setText(String) normalize line endings?
I think that the most likely reasons are:
It would be unexpected behaviour. Most programmers would expect1 a 'get' on a text field to return the same string value that was 'set' ... or that the user entered.
If text fields did normalize, then the programmer would have great difficulty preserving the original text's line endings in vases where this was desirable.
The designers might have wanted to change their minds at some point (c.f. the reported behaviour of the read and write methods) bur were unable to for reasons of compatibility.
Anyway, if you need normalization, there's nothing stopping your code from doing this on the value retrieved by the setter.
Or any other method that allows text to be modified within a text component for that matter?
It is reported (see comments) that read and/or write do normalization.
Is using System.getProperty('line.separator') a good practice when dealing with text components? Is it a good practice at all?
It depends on the context. If you know you are reading and writing files to be processed on "this" platform, its probably a good idea. If the file is intended to be read on a different platform (with a different line separators) then normalizing to match the current machine's convention is maybe a bad idea.
1 - The fact that other methods like read and write that may behave differently doesn't affect this. They are not "getters" and "setters". I'm talking about how people expect "getters" and "setters" to behave ... not anything else. Besides, people shouldn't expect everything to behave the same way, unless it is specified that they do. But obviously, the part of the problem here is that the spec ... the javadocs ... is silent on these issues.
The other possibility is that the normalization behaviour that #predi reports is actually happening in the Reader / Writer objects ...
Using the system line separator is questionable. I would only use it to write text files in platform specific format.
When reading, I always simply throw away any '\r', (CR) effectively converting down Windows/Mac/Unix to Unix-style linefeeds. Internally I would never use anything other than plain '\n' (LF) to indicate linefeeds - its a waste of memory and makes processing text only more painful.
Related
I want to have a setting system that I can read write and use variables from the are stored in a file.
To summarize, There is a class and inside that class is a list of settings.
When I make a setting I want to add it to the list so that I can write it to the text file later.
I also want to be able to get the setting value without casting it which would use generics.
So for boolSetting I would only need to do boolSetting.get() or boolSetting.value ect
To start with code I have already written I have the code to read and write to the file. This works perfect (I think). I just need help with the setting part. Here is the read and write to file.
package winter.settings;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import net.minecraft.src.Config;
import winter.Client;
public class WinterSettings {
public static File WinterSetting;
public static void readSettings() {
try {
File WinterSetting = new File(System.getProperty("user.dir"), "WinterSettings.txt");
BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(new FileInputStream(WinterSetting), "UTF-8"));
String s = "";
while ((s = bufferedreader.readLine()) != null)
{
System.out.println(s);
String[] astring = s.split(":");
Client.modules.forEach(m ->{
if(m.name==astring[0]) {
m.settings.forEach(setting ->{
if(setting.name==astring[1]) {
setting.value=astring[2];
}
});
}
});
}
bufferedreader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writeSettings() {
try {
File WinterSetting = new File(System.getProperty("user.dir"), "WinterSettings.txt");
PrintWriter printwriter = new PrintWriter(new FileWriter(WinterSetting));
Client.modules.forEach(m ->{
m.settings.forEach(setting ->{
printwriter.println(m.name+":"+setting.name+":"+setting.value);
});
});
printwriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Pretty much how this works is I have a setting in a Module which just stores some information.
The setting has a name and a value
To write it I am just writing
The module name, the setting name, the setting value For example: ModuleName:SettingName:false
This works fine, but leads to the problem that I just don't know enough about generics. I can't find a way that works with writing reading and setting / getting. The setting should have a name and value. Some code I wrote is below I just don't know how to continue it.
public class Setting<T> {
public String name;
public T value;
public Setting(String name, T value) {
this.name = name;
this.value = value;
}
public T getValue() {
return value;
}
}
From here I have subclasses for each type of setting. Not sure if this is good programming or not.
Now I can set get / write, but when I read the value isn't updated correctly.
Right now I make a new setting like
private final BooleanSetting toggleSprint = new BooleanSetting("ToggleSprint", true);
There is one problem to this from what I can tell. First off when I try to add it to a list when initilizing I get an error.
Type mismatch: cannot convert from boolean to BooleanSetting.
In short: I need to be able to read write get and set a value in a setting object. This can be boolean / int / ect.
Above is some of my code to read / write to txt file. Setting class and what I have of making a new setting.
My 2 problems are that I read the settings correctly and when making them I can't add them to a list.
Use the Boolean.True static variable
new BooleanSetting("ToggleSprint", Boolean.TRUE);
or
Boolean.valueOf(true)
I am using pdf-clown with pdfclown-0.2.0-HEAD.jar.I have written below code for highlighting search the keyword in Chinese language pdf file and same code is working fine with english pdf file.
import java.awt.Color;
import java.awt.Desktop;
import java.awt.geom.Rectangle2D;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.io.BufferedInputStream;
import java.io.File;
import org.pdfclown.documents.Page;
import org.pdfclown.documents.contents.ITextString;
import org.pdfclown.documents.contents.TextChar;
import org.pdfclown.documents.contents.colorSpaces.DeviceRGBColor;
import org.pdfclown.documents.interaction.annotations.TextMarkup;
import org.pdfclown.documents.interaction.annotations.TextMarkup.MarkupTypeEnum;
import org.pdfclown.files.SerializationModeEnum;
import org.pdfclown.util.math.Interval;
import org.pdfclown.util.math.geom.Quad;
import org.pdfclown.tools.TextExtractor;
public class pdfclown2 {
private static int count;
public static void main(String[] args) throws IOException {
highlight("ebook.pdf","C:\\Users\\Downloads\\6.pdf");
System.out.println("OK");
}
private static void highlight(String inputPath, String outputPath) throws IOException {
URL url = new URL(inputPath);
InputStream in = new BufferedInputStream(url.openStream());
org.pdfclown.files.File file = null;
try {
file = new org.pdfclown.files.File("C:\\Users\\Desktop\\pdf\\test123.pdf");
Map<String, String> m = new HashMap<String, String>();
m.put("亿元或","hi");
m.put("收入亿来","hi");
System.out.println("map size"+m.size());
long startTime = System.currentTimeMillis();
// 2. Iterating through the document pages...
TextExtractor textExtractor = new TextExtractor(true, true);
for (final Page page : file.getDocument().getPages()) {
Map<Rectangle2D, List<ITextString>> textStrings = textExtractor.extract(page);
for (Map.Entry<String, String> entry : m.entrySet()) {
Pattern pattern;
String serachKey = entry.getKey();
final String translationKeyword = entry.getValue();
/*
if ((serachKey.contains(")") && serachKey.contains("("))
|| (serachKey.contains("(") && !serachKey.contains(")"))
|| (serachKey.contains(")") && !serachKey.contains("(")) || serachKey.contains("?")
|| serachKey.contains("*") || serachKey.contains("+")) {s
pattern = Pattern.compile(Pattern.quote(serachKey), Pattern.CASE_INSENSITIVE);
}
else*/
pattern = Pattern.compile(serachKey, Pattern.CASE_INSENSITIVE);
// 2.1. Extract the page text!
//System.out.println(textStrings.toString().indexOf(entry.getKey()));
// 2.2. Find the text pattern matches!
final Matcher matcher = pattern.matcher(TextExtractor.toString(textStrings));
// 2.3. Highlight the text pattern matches!
textExtractor.filter(textStrings, new TextExtractor.IIntervalFilter() {
public boolean hasNext() {
// System.out.println(matcher.find());
// if(key.getMatchCriteria() == 1){
if (matcher.find()) {
return true;
}
/*
* } else if(key.getMatchCriteria() == 2) { if
* (matcher.hitEnd()) { count++; return true; } }
*/
return false;
}
public Interval<Integer> next() {
return new Interval<Integer>(matcher.start(), matcher.end());
}
public void process(Interval<Integer> interval, ITextString match) {
// Defining the highlight box of the text pattern
// match...
System.out.println(match);
/* List<Quad> highlightQuads = new ArrayList<Quad>();
{
Rectangle2D textBox = null;
for (TextChar textChar : match.getTextChars()) {
Rectangle2D textCharBox = textChar.getBox();
if (textBox == null) {
textBox = (Rectangle2D) textCharBox.clone();
} else {
if (textCharBox.getY() > textBox.getMaxY()) {
highlightQuads.add(Quad.get(textBox));
textBox = (Rectangle2D) textCharBox.clone();
} else {
textBox.add(textCharBox);
}
}
}
textBox.setRect(textBox.getX(), textBox.getY(), textBox.getWidth(), textBox.getHeight());
highlightQuads.add(Quad.get(textBox));
}*/
List<Quad> highlightQuads = new ArrayList<Quad>();
List<TextChar> textChars = match.getTextChars();
Rectangle2D firstRect = textChars.get(0).getBox();
Rectangle2D lastRect = textChars.get(textChars.size()-1).getBox();
Rectangle2D rect = firstRect.createUnion(lastRect);
highlightQuads.add(Quad.get(rect).get(rect));
// subtype can be Highlight, Underline, StrikeOut, Squiggly
new TextMarkup(page, highlightQuads, translationKeyword, MarkupTypeEnum.Highlight);
}
public void remove() {
throw new UnsupportedOperationException();
}
});
}
}
SerializationModeEnum serializationMode = SerializationModeEnum.Standard;
file.save(new java.io.File(outputPath), serializationMode);
System.out.println("file created");
long endTime = System.currentTimeMillis();
System.out.println("seconds take for execution is:"+(endTime-startTime)/1000);
} catch (Exception e) {
e.printStackTrace();
}
finally{
in.close();
}
}
}
Kindly provide your inputs to highlight specific search keyword for non english pdf files.
I am serching the keyword in below text which is in chinese langauage.
普双套习近平修宪普京利用双套车绕开宪法装班要走普京
enter image description here
Your PDF Clown version
The PDF Clown version you retrieved here from Tymate's maven repository on github has been pushed there April 23rd, 2015. The final (as of now) check-in to the PDF Clown subversion source code repository TRUNK on sourceforge, on the other hand, is from May 27th, 2015. There actually are some 30 checkins after April 23rd, 2015. Thus, you definitely do not use the most current version of this apparently dead PDF library project.
Using the current 0.2.0 snapshot
I tested your code with the 0.2.0 development version compiled from that trunk and the result indeed is different:
It is better insofar as the highlights have the width of the sought character and are located nearer to the actual character position. There still is a bug, though, as the second and third match highlights are somewhat off.
Fixing the bug
The remaining problem actually is not related to the language of the text. It simply is a bug in the processing of one type of the PDF text drawing commands, so it can be observed in documents with text in arbitrary languages. Due to the fact that these commands nowadays are used very seldom only, though, the bug is hardly ever observed, let alone reported. Your PDF, on the other hand, makes use of that kind of text drawing commands.
The bug is in the ShowText class (package org.pdfclown.documents.contents.objects). At the end of the scan method the text line matrix in the graphics state is updated like this if the ShowText instance actually is a ShowTextToNextLine instance derived from it:
if(textScanner == null)
{
state.setTm(tm);
if(this instanceof ShowTextToNextLine)
{state.setTlm((AffineTransform)tm.clone());}
}
The text line matrix here is set to the text matrix after the move to the next line and the drawing of the text. This is wrong, it must instead be set to text matrix right after the move to the next line before the drawing of the text.
This can be fixed e.g. like this:
if(textScanner == null)
{
state.setTm(tm);
if(this instanceof ShowTextToNextLine)
state.getTlm().concatenate(new AffineTransform(1, 0, 0, 1, 0, -state.getLead()));
}
With this change in place the result looks like this:
I am able to easily print the contents of a JTable mainly through using the statement below. However, this does not work for printing the contents of a textarea component. Is there a simple way of printing the contents of a textarea component? I've seen some pretty confusing examples on the web that use multiple classes. But I'm trying to find a simpler way of doing this.
I ADDED THE SECOND AREA OF CODE ABOUT 24 HOURS AFTER THE ORIGINAL POST. NOTE THAT IT SEEMS TO BE PROMISING BUT PRODUCES THE ERROR "ADD ARGUMENT TO MATCH PRINT(GRAPHICS)". HOW CAN THAT CODE BE FIXED?
table.print(JTable.PrintMode.NORMAL, header, footer);
JButton btnNewButton_7 = new JButton("Print");
btnNewButton_7.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
try{
boolean complete = textArea_2.print();
//The above line reads the error "Add argument to match print(Graphics)"
if(complete){
JOptionPane.showMessageDialog(null, "Printjob Finished", "Report",
JOptionPane.INFORMATION_MESSAGE);
}else{
JOptionPane.showMessageDialog(null, "Printing", "Printer", JOptionPane.ERROR_MESSAGE);
}
}catch(PrinterException e){JOptionPane.showMessageDialog(null, e);
}
}
});
Google and the JavaDocs are your friend
JTextArea#print
A convenience print method that displays a print dialog, and then
prints this JTextComponent in interactive mode with no header or
footer text. Note: this method blocks until printing is done. Note: In
headless mode, no dialogs will be shown.
This method calls the full featured print method to perform
printing.
Returns: true, unless printing is canceled by the user
JTextArea#print(MessageFormat headerFormat, MessageFormat footerFormat)
A convenience print method that displays a print dialog, and then
prints this JTextComponent in interactive mode with the specified
header and footer text. Note: this method blocks until printing is
done. Note: In headless mode, no dialogs will be shown.
This method calls the full featured print method to perform printing.
Parameters: headerFormat - the text, in MessageFormat, to be used as
the header, or null for no header footerFormat - the text, in
MessageFormat, to be used as the footer, or null for no footer
Returns: true, unless printing is canceled by the user
JTextArea#print(MessageFormat headerFormat, MessageFormat footerFormat, boolean showPrintDialog, PrintService service, PrintRequestAttributeSet attributes, boolean interactive) throws PrinterException
...You can look that one yourself, it's to long to post...
JTextArea#getPrintable(MessageFormat headerFormat, MessageFormat footerFormat)
Returns a Printable to use for printing the content of this
JTextComponent. The returned Printable prints the document as it looks
on the screen except being reformatted to fit the paper. The returned
Printable can be wrapped inside another Printable in order to create
complex reports and documents. The returned Printable shares the
document with this JTextComponent. It is the responsibility of the
developer to ensure that the document is not mutated while this
Printable is used. Printing behavior is undefined when the document is
mutated during printing.
Page header and footer text can be added to the output by providing
MessageFormat arguments. The printing code requests Strings from the
formats, providing a single item which may be included in the
formatted string: an Integer representing the current page number.
The returned Printable when printed, formats the document content
appropriately for the page size. For correct line wrapping the
imageable width of all pages must be the same. See
PageFormat.getImageableWidth().
This method is thread-safe, although most Swing methods are not.
Please see How to Use Threads for more information.
The returned Printable can be printed on any thread.
This implementation returned Printable performs all painting on the
Event Dispatch Thread, regardless of what thread it is used on.
Parameters: headerFormat - the text, in MessageFormat, to be used as
the header, or null for no header footerFormat - the text, in
MessageFormat, to be used as the footer, or null for no footer
Returns: a Printable for use in printing content of this
JTextComponent
Works just fine for me...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PrinterException;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestPrint {
public static void main(String[] args) {
new TestPrint();
}
public TestPrint() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JTextArea ta = new JTextArea(20, 100);
try (FileReader reader = new FileReader(new File("C:/Script.txt"))) {
ta.read(reader, ta);
} catch (IOException ex) {
ex.printStackTrace();
}
JButton print = new JButton("Print");
print.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
MessageFormat header = new MessageFormat("Star Wars IV A new Hope");
MessageFormat footer = new MessageFormat("Page {0}");
try {
ta.print(header, footer);
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(ta));
frame.add(print, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Sorry in advance if this has been answered elsewhere, i am probably just searching the wrong tags.
I wish to create a log file, of various variables, with the use of an anonymous inner class implementing ActionListener. This will be attached to a JButton.
Using the Formatter, gives me exactly what i require in a line, but i want to keep
all previous logs of this event (I dont care if its before or after the last entry).
After various methods of me hitting a wall I found through some surfing of this site and others you can possibly do this with an append method in a constructor with Formatter.
Is it possible to use append while in an inner class with Formatter?
If not can you suggest another Java writer that will still meet my needs?
I'm still a beginner so the less complicated the better...for now.
If it's possible within the inner class and with formatter without any additional
imports/packages, please give us a hint or a link and i will keep searching.
I have attached a small compilable sample code, that may help if anyone is interested in
having a play.
thanks,
weekendwarrior84
import java.awt.FlowLayout;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Formatter;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class TestProgram extends JFrame{
private FlowLayout lay;
public TestProgram(){
super("Sample Program");
lay = new FlowLayout();
setLayout(lay);
final JLabel label1 = new JLabel("Label One");
add(label1);
final TextField field1 = new TextField(8);
add(field1);
final JLabel label2 = new JLabel("Exception Label");
add(label2);
final JButton button1 = new JButton
("Log Data");
add(button1);
button1.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){
if(button1.isSelected());
try{
Formatter fm = new Formatter("C:\\Test\\testlog.txt");
fm.format("%s%s%s%s", "Sample Value: ",label1.getText(),
" Sample Value2: ",field1.getText());
fm.close();
}
catch(Exception ee){
label2.setText("Make Sure Path exists, C:\\Test\\testlog.txt");
}
}
}
);
}
}
Main
import javax.swing.JFrame;
public class TestMain{
public static void main (String[] args){
TestProgram ts = new TestProgram();
ts.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ts.setSize(1200,500);
ts.setVisible(true);
}
}
Is there a specific reason why you want to do this with Formatter? It reads like you want to do some very basic logging, for which there are numerous implementations in Java to do the dirty work for you. Even the java.util.logging package would suffice to append log-lines to a file upon button-click. I'd personally suggest logback, but that's just a preference.
If you do insist on doing the file operations yourself this question's answers might be for you. The formatting can just be done with the MessageFormat-class before writing the complete line to the file.
As Promised, it is still a WIP but it solved my current problem. It was mainly confusion on what was possible with the writers, and the belief i required the formatter.
if(button1.isSelected());
String path = "C:\\Test\\testlog.txt";
String mylog = "\r\n"+"Sample Value: " + label1.getText()+" Sample Value2: "+field1.getText();
File file = new File(path);
FileWriter writer;
try {
writer = new FileWriter(file,true);
BufferedWriter buffer = new BufferedWriter(writer);
writer.append(mylog);
buffer.close();
}catch (IOException e1) {
label2.setText("Make Sure Path exists, C:\\Test\\testlog.txt");
i have to do this: i have one JTextField and button. And when i write to that TextField output must show result in JLabel.
Asks the user to provide the name of a class.
Uses Class.forName() to get an access to Java Reflection API.
Creates a new instance (i.e. object) of the class using the default constructor.
Finds and displays all fields of the class in the form including inherited fields:
field_type field_name: (field_value(JTextField))(Set(Button))
field_value must be a textbox, so that the user can change the value by pressing ‘Set’ button. The new value must be updated to the object. If the field contains values of complex types (objects, collections etc.) then the textbox and ‘Set’ button should not be created.
Finds and displays all methods of the class including inherited methods:
return_type method_name (param_type1 (param_value1(JTextField)), param_type2(param_value2(JTextField)) , ..) (Invoke(Button))
If a method has parameters of complex types (objects, collections etc.) then only parameters’ types are displayed, param_values’ textboxes and ‘invoke’ button are skipped.
When the user presses “invoke” button, the application must invoke the method. Make sure that if the method alters the fields’ values these changes are displayed.
and my code here:
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.StringBuffer;
import java.util.Scanner;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class ReflectionTest {
private String class_name = "java.lang.StringBuffer";
public ReflectionTest() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException{
JLabel jl1 = null, jl2, jl3, jl4;
JFrame jf = new JFrame("New");
JPanel jp = new JPanel();
JTextField jtf = new JTextField(20);
JButton jb = new JButton("Press");
jtf.setVisible(true);
jp.add(jb);
jp.add(jtf);
jf.add(jp);
jf.setVisible(true);
jf.setSize(400, 550);
jf.setResizable(false);
String text = jtf.getText().toString();
Class cs = Class.forName(text);
jb.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
// THIS CODE IS EXECUTED WHEN RETURN IS TYPED
}
}
);
for(Constructor c: cs.getConstructors()){
for(Class p: c.getParameterTypes())
System.out.print(p.getName()+" ");
System.out.println();
}
Constructor c = cs.getConstructor(new Class[]{String.class});
Object list = c.newInstance("AA");
Field pub_fields[] = cs.getFields();
Field all_fields[] = cs.getDeclaredFields();
System.out.println("Public fields:");
for(Field f:pub_fields){
//Showing public fields
System.out.println();
jl1 = new JLabel(f.getType().getName() + " " + f.getName());
jp.add(jl1);
jl1.setVisible(true);
}
System.out.println("All declared fields:");
for(Field f:all_fields){
//Showing all declared fields
jl2 = new JLabel(f.getType().getName() + " "+f.getName()+" ");
jp.add(jl2);
jl2.setVisible(true);
f.setAccessible(true);
Object val = f.get(list);
if (val != null){
//System.out.println(val.toString());
jl3 = new JLabel(val.toString());
jp.add(jl3);
jl3.setVisible(true);
System.out.println();
}
else{
System.out.println("NULL");
//f.get(list1);
}
}
}
/**
* #param args
* #throws ClassNotFoundException
*/
public static void main(String[] args) {
try{
// TODO Auto-generated method stub
new ReflectionTest();
}
catch (Exception e){
e.printStackTrace();
}
}
}
and i have error. Eclipse show it in this line:
Class cs = Class.forName(text);
If you test the text String before the exception occurs, for instance by printing it out:
System.out.printf("text = \"%s\"%n", text);
Class cs = Class.forName(text);
Which returns:
text = ""
java.lang.ClassNotFoundException:
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at pkg.ReflectionTest.<init>(ReflectionTest.java:42)
at pkg.ReflectionTest.main(ReflectionTest.java:102)
You'll see that the text String is empty, "". This is because you have no text when you call the Class cs = Class.forName(text); since it's being called before the GUI has been rendered, much less give the user time to enter text. Only call this in code that is called due to a user-generated event of some sort such as an ActionListener's actionPerformed method.
In other words, add the critical code to where in your own commment you state you should add the code:
jb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// THIS CODE IS EXECUTED WHEN RETURN IS TYPED // *********!!!!
}
});
And I second the comment that you should show any and all information about the exception. Please don't make us guess what the problem is.
Edit
Also you will have a problem with using local variables, including the JLabels and JTextField, inside of the anonymous inner listener class. The easiest and best way to solve this is to make the variables that need to be accessed in this listener private class fields. So remove their declarations from the constructor and instead move them to the class itself.
Is it really an error or a "yellow" line? Class is a parametized type and if you do not use generics then eclipse will show a warning.
To eliminate such a warning, simply do a
Class<?> cs = Class.forName(text);
The wildcard is ok because you really don't know which "type" of Class you're going to load.