 |
My most-used utility methods
Posted by enicholas on October 17, 2006 at 10:48 AM | Comments (13)
I've been writing Java code for more than a decade now, and there are a handful of methods I've ended up copying & pasting (or, sadly, reimplementing) in virtually every program I've ever written. I'm not sure why these methods in particular seem to keep cropping up again and again, but nevertheless I end up using them everywhere.
send(InputStream in, OutputStream out)
This method takes data coming from an InputStream and dumps it into an OutputStream. This is useful for a lot of different things -- you can take data sent to you by a web server and dump it into a FileOutputStream, you can take the output and error streams of a process and dump them to System.out and System.err, and on and on.
public static void send(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[2048];
int c;
while ((c = in.read(buffer)) > 0)
out.write(buffer, 0, c);
}
Over the years I've implemented several variations of this basic idea. I've had send() methods that would return the number of bytes they copied, or transfer only a certain number of bytes before stopping, but they've all looked pretty similar.
readFully(InputStream in)
An extension of the send() method, this takes all of the data retrieved from an InputStream and returns it as a byte array for easy processing. This is potentially dangerous, and should only be used when you know in advance that the data is small enough to comfortably fit in memory.
public static byte[] readFully(InputStream in) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
send(in, buffer);
return buffer.toByteArray();
}
An obvious variant of this (assuming a similarly modified send() method) is to fail if the data is bigger than some threshold size limit.
Character-based variants
The send() and readFully() methods can be trivially modified to work with Reader, Writer, and String instead of streams and byte arrays.
String replacement
Once upon a time I had a simple method replaceString(String src, String a, String b), which takes a String and replaces all occurrences of sequence A with sequence B. After many RFEs (by myself and others) to include this capability in String itself, along with lots of explanations about how the regular expression features in Java 1.4 did not in fact eliminate the need for this, the replace(CharSequence a, CharSequence b) method was finally added to java.lang.String in Java 1.5.
Now that the capability is in the JRE itself, my ten-year-old replaceString() method has at last been retired for good, and I couldn't be happier about that. Sometimes it's the little things in life...
What about you?
I've written lots of utility methods, of course, but these are the small handful that I seem to always need no matter what I'm doing. Given my background in client/server code, it's perhaps not surprising that they have to do with data transfer. What about you? Any methods that you just can't live without, that you've been copying from program to program for years?
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
I can't live without these, which is why I wrote (and published) them:
http://www.jpevans.com/software/javas/
FWIW, this library includes versions of both of the methods you referred to. They are :
send(InputStream,OutputStream) -> javas.io.Streams.copy(InputStream,OutputStream
and
readFully(InputStream) -> javas.io.Streams.readString(InputStream)
There are also file based versions (in javas.io.File) and so on, as you may expect.
Posted by: lgas on October 17, 2006 at 11:37 AM
-
All of these examples are available in Apache Commons libraries. Commons IO has a class called CopyUtils that allows you to copy to and from byte arrays, streams, readers, writers, in every combination. And Comons Lang has a StringUtils class that's tough to beat.
Posted by: richunger on October 17, 2006 at 11:45 AM
-
Yep, I'm aware that they're present in Commons -- of course, I wrote these methods long before Commons existed and have pretty much just stuck with my own implementations of them :-).
Posted by: enicholas on October 17, 2006 at 12:20 PM
-
String loadProperty(String propertyFile, String property);
void saveProperty(String propertyFile, String property);
Despite the prevalence of XML, I like a good 'ol properties file, but it's annoying having to.. 1) create a file object 2) check to see if it exists 3) if it doesn't exist, create it 4) create an input stream from the file 5) instantiate a properties object 6) load the properties via the input stream 7) get the property from the properties file.
I always end up coding some type of property manager or util methods to conveniently get and fetch the occasional property.
Posted by: haydensteep on October 17, 2006 at 06:46 PM
-
I came up with an enhanced version of send which transfers the data asynchronously, i.e. a background reader thread fills a ring of buffers, while the foreground writer thread flushes the ring of buffers to the OutputStream. The result shows the same performance as the transfer method in the NIO package.
You can use it as File.cat(InputStream, OutputStream) in the TrueZIP project (https://truezip.dev.java.net).
Regards,
Christian
Posted by: christian_schlichtherle on October 18, 2006 at 05:02 AM
-
A method that gets a Collection and returns a Map. The keys and values are obtaied from bean properties of the Collection's elements. I find it very usefull when dealing with small collections of objects that I don't want to put in databases.
Posted by: masvacaquecarnero on October 18, 2006 at 05:25 AM
-
Check.notNull(object);
Check.isEDT();
Check.isNotEDT();
I use notNull() this like:
class Foo {
private final String bar;
Foo(String bar) {
bar = Check.notNull(bar);
}
}
Generics means that I can do this without a cast. Varargs gives a concise variant for multiple arguments.
Posted by: coxcu on October 18, 2006 at 10:15 AM
-
A fellow programmer at work tried truezip, given I suggested it as a possibly easier way to handle zip files, however it had a serious intermittent data loss bug where it lost the end of a file over a 64k boundary; flawed aynchronous I/O maybe to blame for this. I unfortunately had to encourage him to cut his losses and drop truezip, given there rately spare time to debug, and make or request fixes for OSS libraries.
IMHO you should only do asynchronous I/O (preferable via expert designed NIO) when it is actually required (e.g. for network client/server managing multiple connections), it is IMHO unwise for zip files, given the very real danger of data loss and corruption, the buggy java.util.zip package and support JNI does not help here.
I built a sub-class of java.util.Properties which has a nested structure of light weight XML like string nodes, e.g.
database.1.driver=a class name
database.1.url=a url
database.2.driver=a class name
database,2.url=a url
The main benefit is, it is much lighter weight than XML and a value can be accessed either as a full property or as node (yes I had to include some non-public java.util.Properties code for loading and saving). I even added utility getters/setters for properties and nodes, for all primitive types and some object types, great for flexible reuse.
I tend to use a lot of Apache Java libraries, like Commons IO, Commons DB, log4j, regex, otro, Not Commons Lang (I have much better code, including a wicked String aligner factory), however I only include the bare minimum classes (and licences) required in an integrated application jar, to avoid jar bloat and classpath hell. JBuilder makes it dead easy to build these filtered, integrated jars, via multiple GUI editable jar build profiles in the project tree and multiple project specific menu run profiles. NetBeans and Eclipse are still hopeless for this features e.g. the NetBean 5.5 Beta JBuilder Project Importer is a bad joke because NetBeans 5.5 Beta can only support one GUI accessible run profile, one jar build per project and dependencies support is a mess! Yes I have nagged NetBeans about this, without effect.
Posted by: infernoz on October 18, 2006 at 03:19 PM
-
grrr, when is java.net going to support post editing!
Posted by: infernoz on October 18, 2006 at 03:20 PM
-
YES, it drives me mad, too. "HTML allowed" is such a euphemism.
Posted by: mernst on October 19, 2006 at 12:57 AM
-
There are times where I just want to print out a lot of stuff and don’t want to concatenate it together. Mostly I use it for debugging.
public static void println(Object ... args){
System.out.println(Arrays.toString(args));
}
Posted by: aberrant on October 19, 2006 at 07:42 AM
-
@infernoz: Sorry, but your image of TrueZIP and the conclusion is wrong:
TrueZIP does not have a 64k byte limit on file size. TrueZIP comes with comprehensive unit tests, uses assertions heavily and I personally use it for zipping ~50.000 files per day for the last ~18 months. It has never corrupted a single file since then.
File.cat(InputStream, OutputStream) utilizes asynchronous I/O, but always waits for the data to be completely transferred. The asynchronous I/O is just an implementation detail which makes it as fast as transferring the data with NIO.
It's wrong to say that asynchronous I/O shouldn't be applied to regular files or archives. In fact, the reason why so many Java apps still perform poorly when copying data is that they simply loop across the file content with a small buffer. I get mad if I see a Java app with a typical byte buffer size of 1KB - we're living in Gigabyte age and programmers still use byte buffer sizes from the seventies. This is just bad habit.
TrueZIP does not depend on java.util.zip. It comes with its own version of ZipFile|ZipOutputStream.
Posted by: christian_schlichtherle on November 03, 2006 at 12:51 PM
-
I have a Tuple class that I find valuable. I've blogged about it here:
http://www.adventuresinsoftware.com/blog/?p=43
Posted by: michaellperry on November 30, 2006 at 07:41 PM
|