Mostly adding to rolfl's answer really...
1. Style
Indentation and spaces have already been mentioned here, so I won't quote, just re-iterate. The source code above is 36 lines long, not including the import statements that were omitted.
The line System.out.print("Done!");
should probably be done with println()
as the formatting does not look great when the program throws errors.
2. Exceptions
The exceptions need work here. They are almost always one of the first things you take care of in a method that throws them, even before you write the code that could make it happen.
If exceptions aren't set up properly, or clear enough about what has happened then it can lead to unexpected outputs.
For example, due to your empty block mentioned by rolfl, if either "words.txt" or "words1.txt" does not exist, the resulting merged file will not contain the missing content, and still cheerfully prints "Done!" at the end.
Also, a print message from the programmer is usually not enough to tell what has gone on, so e.getMessage()
or e.getStackTrace()
can be helpful if added.
3. Methods, Magic variables
Methods, dude! Always split tasks up into methods when possible, and in particular avoid a giant wall of text in the main()
method. This helps to make the program flow less confusing and easier to debug.
Magic variables in programs can be fine in circumstances where they are declared as final, but I can't really think of a different example. There's usually always a better and more elegant solution.
http://en.wikipedia.org/wiki/Magic_string
If you allow users to enter filenames to merge through the program arguments, then you can do away with the magic input filenames altogether. There is only one magic string here, and it is declared at the TOP:
public class testMain {
private static final String OUTPUT_FILENAME = "mixOfLists.txt";
public static void main( String[] args ) {
if(args.length < 2) {
System.out.println("Must input at least two filenames to merge");
System.exit(1);
}
mergeFiles(args, OUTPUT_FILENAME);
System.out.println("Done!");
System.exit(0);
}
public static void mergeFiles(String[] filesToMerge,
String outputFilename) { ...
Here, I have left the output filename as a constant to make the arguments easier to enter and process. The mergeFiles method still takes the input and ouput paramaters in case you want to use this method again.
4. Variable Names
Good variable names reveal what they are there for at first glance.
while(s.hasNextLine()){
is rather cryptic. Names like in
, out
, scanner
are all fairly short and are effective.
5. Efficiency
I've found in Java that the variable that makes the most difference in performance is memory usage; if your memory usage is low, then your program is very likely to run fast.
I tested a basic file with ~120 000 lines and got memory improvements of ~6x better when using the Buffered's
-Don't declare variables too long before you need to use them and they can go out of scope. The output filename is the only variable here that needs to be declared outside the try blocks, as all the file data can be read, written, closed and then forgotten about.
This is the implementation I came up with (very basic still). Not including the import statements it is 45 lines long, only 9 longer than the original :)
public class testMain {
private static final String OUTPUT_FILENAME = "mixOfLists.txt";
public static void main( String[] args ) {
if(args.length < 2) {
System.out.println("Must input at least two filenames to merge");
System.exit(1);
}
mergeFiles(args, OUTPUT_FILENAME);
System.out.println("Done!");
System.exit(0);
}
private static void mergeFiles(String[] filesToMerge,
String outputFilename) {
try {
HashSet<String> mergeSet = new HashSet<>();
BufferedWriter out =
new BufferedWriter(new FileWriter(outputFilename));
for(String filename : filesToMerge) {
BufferedReader in = new BufferedReader(
new FileReader(filename));
String temp;
while( (temp = in.readLine()) != null ) {
if(mergeSet.add(temp)) {
out.write(temp);
}
}
in.close();
}
out.close();
} catch ( FileNotFoundException e ) {
System.err.println("File not found: "+ e.getStackTrace());
System.exit(1);
} catch ( IOException e ) {
System.err.println("File error occurred: " + e.getStackTrace());
System.exit(1);
}
}
}