runtime.exec with spaces in the parameters - java

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

Related

Java Scanner class fails in tokenization when 1024 character is the delimeter

I've found a strange behaviour of java.util.Scanner class.
I need to split a String variable into a set of tokens separated by ";".
If I consider a string of "a[*1022]" + ";[*n]" I expect a number n of token.
However if n=3 the Scanner class fails: it "see" just 2 tokens instead of 3. I think it's something related to internal char buffer size of Scanner class.
a[x1022]; -> 1 token: correct
a[x1022];; -> 2 token: correct
a[x1022];;; -> 2 token: wrong (I expect 3 tokens)
a[x1022];;;; -> 4 token: correct
I attach a simple example:
import java.util.Scanner;
public static void main(String[] args) {
// generate test string: (1022x "a") + (3x ";")
String testLine = "";
for (int i = 0; i < 1022; i++) {
testLine = testLine + "a";
}
testLine = testLine + ";;;";
// set up the Scanner variable
String delimeter = ";";
Scanner lineScanner = new Scanner(testLine);
lineScanner.useDelimiter(delimeter);
int p = 0;
// tokenization
while (lineScanner.hasNext()){
p++;
String currentToken = lineScanner.next();
System.out.println("token" + p + ": '" + currentToken + "'");
}
lineScanner.close();
}
I would like to skip the "incorrect" behaviour, could you help me?
Thanks
My recommendation is to report the bug to Oracle, and then work around it by using a BufferedReader to read your InputStream (you'll also need the InputStreamReader class). What Scanner does isn't magic, and working directly with BufferedReader in this case only requires slightly more code than you were already using.

Unit Testing for JMenuItem

I am new to JUnit testing. I am trying to test a method that exports a report. Basically, this method pops up a save menu to select where to save the file at and also gets the report from another class. I am not sure what I need to test here or how to even test it. I have added my JMenuItem and my actionEvent as well. Any ideas or help would be greatly accepted.
Here is my JMenuItem:
JMenuItem jMenuFileexportProjectReport = new JMenuItem(exportProjectReportAction);
Here is my Action event for the JMenuItem:
public Action exportProjectReportAction =
new AbstractAction(Local.getString("Export Project Report")) {
public void actionPerformed(ActionEvent e) {
reportExportAction(e);
}
};
Here is my method to export the report:
public void reportExportAction(ActionEvent e) {
JFileChooser chooser = new JFileChooser();
chooser.setFileHidingEnabled(false);
chooser.setDialogTitle(Local.getString("Export Project Report"));
chooser.setAcceptAllFileFilterUsed(false);
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
chooser.addChoosableFileFilter(
new AllFilesFilter(AllFilesFilter.XHTML));
chooser.addChoosableFileFilter(new AllFilesFilter(AllFilesFilter.HTML));
String lastSel = (String) Context.get("LAST_SELECTED_EXPORT_FILE");
if (lastSel != null) {
chooser.setCurrentDirectory(new File(lastSel));
}
ProjectExportDialog dlg =
new ProjectExportDialog(
App.getFrame(),
Local.getString("Export Project Report"),
chooser);
String enc = (String) Context.get("EXPORT_FILE_ENCODING");
if (enc != null) {
dlg.encCB.setSelectedItem(enc);
}
Dimension dlgSize = new Dimension(550, 500);
dlg.setSize(dlgSize);
Dimension frmSize = App.getFrame().getSize();
Point loc = App.getFrame().getLocation();
dlg.setLocation(
(frmSize.width - dlgSize.width) / 2 + loc.x,
(frmSize.height - dlgSize.height) / 2 + loc.y);
dlg.setVisible(true);
if (dlg.CANCELLED) {
return;
}
Context.put(
"LAST_SELECTED_EXPORT_FILE",
chooser.getSelectedFile().getPath());
int ei = dlg.encCB.getSelectedIndex();
enc = null;
if (ei == 1) {
enc = "UTF-8";
}
boolean nument = (ei == 2);
File f = chooser.getSelectedFile();
boolean xhtml =
chooser.getFileFilter().getDescription().indexOf("XHTML") > -1;
CurrentProject.save();
ReportExporter.export(CurrentProject.get(), chooser.getSelectedFile(), enc, xhtml,
nument);
}
Class the creates a HTML report:
public class ReportExporter {
static boolean _chunked = false;
static boolean _num = false;
static boolean _xhtml = false;
static boolean _copyImages = false;
static File output = null;
static String _charset = null;
static boolean _titlesAsHeaders = false;
static boolean _navigation = false;
static String charsetString = "\n";
public static void export(Project prj, File f, String charset, boolean xhtml, boolean chunked) {
_chunked = chunked;
_charset = charset;
_xhtml = xhtml;
if (f.isDirectory()) {
output = new File(f.getPath() + "/Project Report.html");
}
else {
output = f;
}
NoteList nl = CurrentStorage.get().openNoteList(prj);
Vector notes = (Vector) nl.getAllNotes();
//Creates Labels for the HTML output for each section.
String notesLabelHTML = "Notes";
String tasksLabelHTML = "Tasks";
String eventsLabHTML = "Events";
//NotesVectorSorter.sort(notes);
Collections.sort(notes);
Writer fw;
if (output.getName().indexOf(".htm") == -1) {
String dir = output.getPath();
String ext = ".html";
String nfile = dir + ext;
output = new File(nfile);
}
try {
if (charset != null) {
fw = new OutputStreamWriter(new FileOutputStream(output),
charset);
charsetString = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset="
+ charset + "\" />";
}
else
fw = new FileWriter(output);
}
catch (Exception ex) {
new ExceptionDialog(ex, "Failed to write to " + output, "");
return;
}
//Writes the title and the notes section of the HTMl Report
write(fw, "<html>\n<head>\n" + charsetString + "<title>"
+ prj.getTitle()
+ "</title>\n</head>\n<body>\n<h1 class=\"projecttitle\">"
+ prj.getTitle() + "</h1>\n" +"\n<br>\n"
+ "</title>\n</head>\n<body>\n<h2 class=\"projecttitle\">"
+ notesLabelHTML + "</h2>\n" );
generateChunks(fw, notes);
//Writes the Task section of the HTML Report
write(fw, "\n<hr></hr><a" +"</title>\n</head>\n<body>\n<h2 class=\"projecttitle\">" + "\n<br>\n"
+ tasksLabelHTML + "</h2>\n" );
//writes the Events section of the HTML Report
write(fw, "\n<hr></hr><a" +"</title>\n</head>\n<body>\n<h2 class=\"projecttitle\">" + "\n<br>\n"
+ eventsLabHTML + "</h2>\n" );
//Writes the ending of the report with the data and time
write(fw, "\n<hr></hr><a "
+ "\n<br></br>\n" + new Date().toString()
+ "\n</body>\n</html>");
try {
fw.flush();
fw.close();
}
catch (Exception ex) {
new ExceptionDialog(ex, "Failed to write to " + output, "");
}
}
public static String getNoteHTML(Note note) {
String text = "";
StringWriter sw = new StringWriter();
AltHTMLWriter writer = new AltHTMLWriter(sw,
(HTMLDocument) CurrentStorage.get().openNote(note), _charset,
_num);
try {
writer.write();
sw.flush();
sw.close();
}
catch (Exception ex) {
new ExceptionDialog(ex);
}
text = sw.toString();
if (_xhtml) {
text = HTMLFileExport.convertToXHTML(text);
}
text = Pattern
.compile("<body(.*?)>", java.util.regex.Pattern.DOTALL
+ java.util.regex.Pattern.CASE_INSENSITIVE).split(text)[1];
text = Pattern
.compile("</body>", java.util.regex.Pattern.DOTALL
+ java.util.regex.Pattern.CASE_INSENSITIVE).split(text)[0];
text = "<div class=\"note\">" + text + "</div>";
if (_titlesAsHeaders) {
text = "\n\n<div class=\"date\">"
+ note.getDate().getFullDateString()
+ ":</div>\n<h1 class=\"title\">" + note.getTitle()
+ "</h1>\n" + text;
}
return text;
}
private static String generateNav(Note prev, Note next) {
String s = "<hr></hr><div class=\"navigation\"><table border=\"0\" width=\"100%\" cellpadding=\"2\"><tr><td width=\"33%\">";
if (prev != null) {
s += "<div class=\"navitem\"><a href=\"" + prev.getId() + ".html\">"
+ Local.getString("Previous") + "</a><br></br>"
+ prev.getDate().getMediumDateString() + " "
+ prev.getTitle() + "</div>";
}
else {
s += " ";
s += "</td><td width=\"34%\" align=\"center\"><a href=\""
+ output.getName()
+ "\">Up</a></td><td width=\"33%\" align=\"right\">";
}
if (next != null) {
s += "<div class=\"navitem\"><a href=\"" + next.getId() + ".html\">"
+ Local.getString("Next") + "</a><br></br>"
+ next.getDate().getMediumDateString() + " "
+ next.getTitle() + "</div>";
}
else {
s += " ";
}
s += "</td></tr></table></div>\n";
return s;
}
private static void generateChunks(Writer w, Vector notes) {
Object[] n = notes.toArray();
for (int i = 0; i < n.length; i++) {
Note note = (Note) n[i];
CalendarDate d = note.getDate();
if (_chunked) {
File f = new File(output.getParentFile().getPath() + "/"
+ note.getId()
+ ".html");
Writer fw = null;
try {
if (_charset != null) {
fw = new OutputStreamWriter(new FileOutputStream(f),
_charset);
}
else {
fw = new FileWriter(f);
}
String s = "<html>\n<head>\n"+charsetString+"<title>" + note.getTitle()
+ "</title>\n</head>\n<body>\n" + getNoteHTML(note);
if (_navigation) {
Note nprev = null;
if (i > 0) {
nprev = (Note) n[i - 1];
}
Note nnext = null;
if (i < n.length - 1) {
nnext = (Note) n[i + 1];
}
s += generateNav(nprev, nnext);
}
s += "\n</body>\n</html>";
fw.write(s);
fw.flush();
fw.close();
}
catch (Exception ex) {
new ExceptionDialog(ex, "Failed to write to " + output, "");
}
}
else {
write(w, "<a name=\"" + "\">" + note.getDate() +"</a>\n" + getNoteHTML(note) + "</a>\n");
}
}
}
private static void write(Writer w, String s) {
try {
w.write(s);
}
catch (Exception ex) {
new ExceptionDialog(ex, "Failed to write to " + output, "");
}
}
As it has already been mentioned, basically you should move out the application logic from the GUI code.
Unit testing usually doesn't work like write working code then add tests to it. First you should think about
what is the testable part of the logic and what isn't
how will you separate them
how will you test the testable part
Directly testing GUI code usually does not work (except with some rare and well-designed UI frameworks), since your test would have to deal with a lot of technical problems (like framework initialization, instantiation of UI objects, triggering events properly, etc). So you should create a more abstract layer of the app. In a bigger picture, it will lead to the well-known Model-View-Controller pattern (de-facto standard design pattern for user interfaces since Smalltalk), where the model layer is independent from the UI framework, therefore it is simply testable.
So as some kind of case study, lets walk through the above concepts:
First lets check what is testable, what isn't and what stops you from writing tests:
chooser.setDialogTitle(Local.getString("Export Project Report"));
This single line deals with both rendering and i18n, not really a good idea. Furthermore, the use of static methods is a top blocker antipattern for writing tests.
String lastSel = (String) Context.get("LAST_SELECTED_EXPORT_FILE");
Static method call here again, also it would be hard to determine the responsibility of that Context class.
Local.getString("Export Project Report")
also a static call, kind of duplicate code too
...and so on (static calls everywhere). Now lets see what kind of more abstract model we can create for this. First lets start with
some textual description of the requirements:
There is a title (used both in the JFileChooser and the ProjectExportDialog) to be internationalized by key "Export Project Report"
there is a previously selected directory (lastSel) which value we take granted at the beginning
the encoding (enc) is similar to enc, nullable value too
the dialog location (positioning) contains some arithmetic, we should test it
if the user selects a file, then we should store it as the last selected directory
there is an opened (current) project too, which we will save at the end
there is something you call "nument", I don't understand what it is, but it should be true if the user selects the 2nd entry from dlg.encCB
Untestable parts:
chooser... calls: UI-specific configuration of the JFileChooser, also it doesn't contain any control structures or calculation, so we won't test it
Now we are going to design a testable model class. While doing it, we will keep two principles in mind:
we are going to put as much logic into the model as we can
we don't want to rewrite your entire app for this time. So instead of getting rid of all the static calls, we abstract them away as simply as possible.
So now lets create some sort of abstract model for this (summary after code):
public class ProjectExportModel {
// see the reasoning below
public static ProjectExportModel create() {
return new ProjectExportModel(Local::getString,
(String) Context.get("LAST_SELECTED_EXPORT_FILE"),
Context::put);
}
private final Function<String, String> i18n;
private final File lastSelectedExportFile;
private final Consumer<File> lastSelectedFileSaver;
private String encoding;
private boolean nument;
private boolean xhtml;
public ProjectExportModel(final Function<String, String> i18n, final File lastSelectedExportFile,
final Consumer<File> lastSelectedFileSaver) {
this.i18n = i18n;
this.lastSelectedExportFile = lastSelectedExportFile;
this.lastSelectedFileSaver = lastSelectedFileSaver;
}
/**
* Called after a file has been selected from the JFileChooser
*
* Things to test:
* - lastSelectedFileSaver.accept(file.getPath()) should be called - you may use a
* mocking library to test
* - the xhtml flag should be changed - testing is easy
*
*/
public void fileSelected(final File file) {
// TODO
}
/**
* At this point we break a bit the concept of the UI-independent model layer, since Point and Dimension
* are UI-framework-related classes. But these 2 classes are easy to instantiate and easy to assert on the
* returned value, so good-enough solution this time.
*/
public Point getDialogLocation(final Dimension frameSize, final Point frameLocation) {
return null; // TODO implement the positioning
}
public String getFrameTitle() {
// TODO test if it calls and returns i18n.get("Export Project Model") - you need mocking here too
return null;
}
/**
* Two things to be tested here:
* - if CurrentProject.save() is called
* - if ReportExporter.export(...) is called with the right parameters
*
* You are quite stuck here, since static methods cannot be mocked. Instead it would be better to change your APIs to make
* these instance methods, since in the current way it is untestable. After changing these to instance methods, you should add
* 2 more parameters to the constructor: a Project instance and a ReportExporter instance.
* You can use mockito or easymock for mocking.
*/
public void save() {
}
/**
* You may call it from the view layer after calling fileSelected().
*
* To be tested:
* - the proper change of the encoding member
* - the proper change of the nument member
*/
public void selectedEncodingChanged(final int selectedIndex) {
// TODO implemenent the change of encoding and nument member
}
}
Summary:
this class is easy to instantiate and test
in the tests you will use its explicit constructor to create instances
for "production" usage, you will have to create a View class, which handles the swing-related code, accepts a ProjectExportModel instance as its parameter, and calls it methods, so you wire the tested model into the untestable UI-related code, while keeping the latter one minimal. Also, in this case you will create the model instance with ProjectExportModel.create() , since that methods wires the further dependencies in a way that it will more or less nicely interact with the other static methods of your app. This is a good technique for extracting testable parts while you don't necessarily have to remove all static methods from the app, we have just separated them away.

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

Write string to a specific position in file

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.

Where and how to start implementing a Java program that searches a phrase example “red or green" in a text file,

I want to implementing a Java program that searches a phrase example “red or green, blue car, red and blue” in a text file, and returns a match even if it is not a complete match for the phrase, and if there is no even half match the program should return no match.
if I am searching "red car" and the the string line in the text file contains "red and blue" I want the program to return red which is half a match of what I was searching.
Any help is very much appreciated
This is what I have done so far, all this does is find the exact words
public class StringSearch
{
public static void main(String[] args)
{
String key = "red yellow";
String strLine;
try
{
FileInputStream fstream = new FileInputStream("C:\\textfile.txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
while ((strLine = br.readLine()) != null) {
if(key.equals(strLine))
{
System.out.println(" Match For " + strLine );
}
else
{
System.out.println( "No Match For " + key);
}
// Print the content on the console
}
//Close the input stream
in.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
}
But what I want to find is if I am searching "red" and the first line of the string in the text file I am searching contains "red car was stollen" and the second line contains just "red". I want to return two matches the first one being 100% match the socond being 50% match.
First you need to define your problem better, and to do that think about how what you'd do if you were telling someone else, who interpreted things very literally, how to do it. How much of the input should they examine at one time? Should what they examine span lines? What precisely is a "half match"? What is the sequence of steps they should take?
This code might help You
import java.io.*;
public class searchfile {
public static void main(String args[]) {
try {
// Open the file c:\test.txt as a buffered reader
BufferedReader bf = new BufferedReader(new FileReader("c:\\test.txt"));
// Start a line count and declare a string to hold our current line.
int linecount = 0;
String line;
// Let the user know what we are searching for
System.out.println("Searching for " + args[0] + " in file...");
// Loop through each line, stashing the line into our line variable.
while (( line = bf.readLine()) != null)
{
// Increment the count and find the index of the word
linecount++;
int indexfound = line.indexOf(args[0]);
// If greater than -1, means we found the word
if (indexfound > -1) {
System.out.println("Word was found at position " + indexfound + " on line " + linecount);
}
}
// Close the file after done searching
bf.close();
}
catch (IOException e) {
System.out.println("IO Error Occurred: " + e.toString());
}
}
}
and run it as
c:\>java searchfile "bluecar"

Categories