1*0c4d7b72SSadaf Ebrahimi<?xml version="1.0"?> 2*0c4d7b72SSadaf Ebrahimi<!-- 3*0c4d7b72SSadaf EbrahimiLicensed to the Apache Software Foundation (ASF) under one or more 4*0c4d7b72SSadaf Ebrahimicontributor license agreements. See the NOTICE file distributed with 5*0c4d7b72SSadaf Ebrahimithis work for additional information regarding copyright ownership. 6*0c4d7b72SSadaf EbrahimiThe ASF licenses this file to You under the Apache License, Version 2.0 7*0c4d7b72SSadaf Ebrahimi(the "License"); you may not use this file except in compliance with 8*0c4d7b72SSadaf Ebrahimithe License. You may obtain a copy of the License at 9*0c4d7b72SSadaf Ebrahimi 10*0c4d7b72SSadaf Ebrahimi http://www.apache.org/licenses/LICENSE-2.0 11*0c4d7b72SSadaf Ebrahimi 12*0c4d7b72SSadaf EbrahimiUnless required by applicable law or agreed to in writing, software 13*0c4d7b72SSadaf Ebrahimidistributed under the License is distributed on an "AS IS" BASIS, 14*0c4d7b72SSadaf EbrahimiWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15*0c4d7b72SSadaf EbrahimiSee the License for the specific language governing permissions and 16*0c4d7b72SSadaf Ebrahimilimitations under the License. 17*0c4d7b72SSadaf Ebrahimi--> 18*0c4d7b72SSadaf Ebrahimi<document> 19*0c4d7b72SSadaf Ebrahimi <properties> 20*0c4d7b72SSadaf Ebrahimi <title>Best practices</title> 21*0c4d7b72SSadaf Ebrahimi <author email="[email protected]">Commons Documentation Team</author> 22*0c4d7b72SSadaf Ebrahimi </properties> 23*0c4d7b72SSadaf Ebrahimi <body> 24*0c4d7b72SSadaf Ebrahimi 25*0c4d7b72SSadaf Ebrahimi <section name="Best practices"> 26*0c4d7b72SSadaf Ebrahimi <p> 27*0c4d7b72SSadaf Ebrahimi This document presents a number of 'best practices' in the IO area. 28*0c4d7b72SSadaf Ebrahimi </p> 29*0c4d7b72SSadaf Ebrahimi </section> 30*0c4d7b72SSadaf Ebrahimi 31*0c4d7b72SSadaf Ebrahimi <section name="java.io.File"> 32*0c4d7b72SSadaf Ebrahimi 33*0c4d7b72SSadaf Ebrahimi <p> 34*0c4d7b72SSadaf Ebrahimi Often, you have to deal with files and filenames. There are many 35*0c4d7b72SSadaf Ebrahimi things that can go wrong: 36*0c4d7b72SSadaf Ebrahimi </p> 37*0c4d7b72SSadaf Ebrahimi <ul> 38*0c4d7b72SSadaf Ebrahimi <li>A class works in Unix but doesn't on Windows (or vice versa)</li> 39*0c4d7b72SSadaf Ebrahimi <li>Invalid filenames due to double or missing path separators</li> 40*0c4d7b72SSadaf Ebrahimi <li>UNC filenames (on Windows) don't work with my home-grown filename utility function</li> 41*0c4d7b72SSadaf Ebrahimi <li>etc. etc.</li> 42*0c4d7b72SSadaf Ebrahimi </ul> 43*0c4d7b72SSadaf Ebrahimi <p> 44*0c4d7b72SSadaf Ebrahimi These are good reasons not to work with filenames as Strings. 45*0c4d7b72SSadaf Ebrahimi Using java.io.File instead handles many of the above cases nicely. 46*0c4d7b72SSadaf Ebrahimi Thus, our best practice recommendation is to use java.io.File 47*0c4d7b72SSadaf Ebrahimi instead of String for filenames to avoid platform dependencies. 48*0c4d7b72SSadaf Ebrahimi </p> 49*0c4d7b72SSadaf Ebrahimi <p> 50*0c4d7b72SSadaf Ebrahimi <i> 51*0c4d7b72SSadaf Ebrahimi Version 1.1 of commons-io now includes a dedicated filename 52*0c4d7b72SSadaf Ebrahimi handling class - <a href="apidocs/index.html?org/apache/commons/io/FilenameUtils.html">FilenameUtils</a>. 53*0c4d7b72SSadaf Ebrahimi This does handle many of these filename issues, however we still 54*0c4d7b72SSadaf Ebrahimi recommend, wherever possible, that you use java.io.File objects. 55*0c4d7b72SSadaf Ebrahimi </i> 56*0c4d7b72SSadaf Ebrahimi </p> 57*0c4d7b72SSadaf Ebrahimi <p> 58*0c4d7b72SSadaf Ebrahimi Let's look at an example. 59*0c4d7b72SSadaf Ebrahimi </p> 60*0c4d7b72SSadaf Ebrahimi <source> 61*0c4d7b72SSadaf Ebrahimi public static String getExtension(String filename) { 62*0c4d7b72SSadaf Ebrahimi int index = filename.lastIndexOf('.'); 63*0c4d7b72SSadaf Ebrahimi if (index == -1) { 64*0c4d7b72SSadaf Ebrahimi return ""; 65*0c4d7b72SSadaf Ebrahimi } else { 66*0c4d7b72SSadaf Ebrahimi return filename.substring(index + 1); 67*0c4d7b72SSadaf Ebrahimi } 68*0c4d7b72SSadaf Ebrahimi }</source> 69*0c4d7b72SSadaf Ebrahimi <p> 70*0c4d7b72SSadaf Ebrahimi Easy enough? Right, but what happens if someone passes in a full path 71*0c4d7b72SSadaf Ebrahimi instead of only a filename? Consider the following, perfectly legal path: 72*0c4d7b72SSadaf Ebrahimi "C:\Temp\documentation.new\README". 73*0c4d7b72SSadaf Ebrahimi The method as defined above would return "new\README" - definitely 74*0c4d7b72SSadaf Ebrahimi not what you wanted. 75*0c4d7b72SSadaf Ebrahimi </p> 76*0c4d7b72SSadaf Ebrahimi <p> 77*0c4d7b72SSadaf Ebrahimi Please use java.io.File for filenames instead of Strings. 78*0c4d7b72SSadaf Ebrahimi The functionality that the class provides is well tested. 79*0c4d7b72SSadaf Ebrahimi In FileUtils you will find other useful utility functions 80*0c4d7b72SSadaf Ebrahimi around java.io.File. 81*0c4d7b72SSadaf Ebrahimi </p> 82*0c4d7b72SSadaf Ebrahimi <p> 83*0c4d7b72SSadaf Ebrahimi Instead of: 84*0c4d7b72SSadaf Ebrahimi </p> 85*0c4d7b72SSadaf Ebrahimi <source> 86*0c4d7b72SSadaf Ebrahimi String tmpdir = "/var/tmp"; 87*0c4d7b72SSadaf Ebrahimi String tmpfile = tmpdir + System.getProperty("file.separator") + "test.tmp"; 88*0c4d7b72SSadaf Ebrahimi InputStream in = new java.io.FileInputStream(tmpfile);</source> 89*0c4d7b72SSadaf Ebrahimi <p> 90*0c4d7b72SSadaf Ebrahimi ...write: 91*0c4d7b72SSadaf Ebrahimi </p> 92*0c4d7b72SSadaf Ebrahimi <source> 93*0c4d7b72SSadaf Ebrahimi File tmpdir = new File("/var/tmp"); 94*0c4d7b72SSadaf Ebrahimi File tmpfile = new File(tmpdir, "test.tmp"); 95*0c4d7b72SSadaf Ebrahimi InputStream in = new java.io.FileInputStream(tmpfile);</source> 96*0c4d7b72SSadaf Ebrahimi 97*0c4d7b72SSadaf Ebrahimi </section> 98*0c4d7b72SSadaf Ebrahimi 99*0c4d7b72SSadaf Ebrahimi <section name="Buffering streams"> 100*0c4d7b72SSadaf Ebrahimi <p> 101*0c4d7b72SSadaf Ebrahimi IO performance depends a lot on the buffering strategy. Usually, it's 102*0c4d7b72SSadaf Ebrahimi quite fast to read packets with the size of 512 or 1024 bytes because 103*0c4d7b72SSadaf Ebrahimi these sizes match well with the packet sizes used on hard disks in 104*0c4d7b72SSadaf Ebrahimi file systems or file system caches. But as soon as you have to read only 105*0c4d7b72SSadaf Ebrahimi a few bytes and that many times performance drops significantly. 106*0c4d7b72SSadaf Ebrahimi </p> 107*0c4d7b72SSadaf Ebrahimi <p> 108*0c4d7b72SSadaf Ebrahimi Make sure you're properly buffering streams when reading or writing 109*0c4d7b72SSadaf Ebrahimi streams, especially when working with files. Just decorate your 110*0c4d7b72SSadaf Ebrahimi FileInputStream with a BufferedInputStream: 111*0c4d7b72SSadaf Ebrahimi </p> 112*0c4d7b72SSadaf Ebrahimi <source> 113*0c4d7b72SSadaf Ebrahimi InputStream in = new java.io.FileInputStream(myfile); 114*0c4d7b72SSadaf Ebrahimi try { 115*0c4d7b72SSadaf Ebrahimi in = new java.io.BufferedInputStream(in); 116*0c4d7b72SSadaf Ebrahimi 117*0c4d7b72SSadaf Ebrahimi in.read(..... 118*0c4d7b72SSadaf Ebrahimi } finally { 119*0c4d7b72SSadaf Ebrahimi IOUtils.closeQuietly(in); 120*0c4d7b72SSadaf Ebrahimi }</source> 121*0c4d7b72SSadaf Ebrahimi <p> 122*0c4d7b72SSadaf Ebrahimi Pay attention that you're not buffering an already buffered stream. Some 123*0c4d7b72SSadaf Ebrahimi components like XML parsers may do their own buffering so decorating 124*0c4d7b72SSadaf Ebrahimi the InputStream you pass to the XML parser does nothing but slowing down 125*0c4d7b72SSadaf Ebrahimi your code. If you use our CopyUtils or IOUtils you don't need to 126*0c4d7b72SSadaf Ebrahimi additionally buffer the streams you use as the code in there already 127*0c4d7b72SSadaf Ebrahimi buffers the copy process. Always check the Javadocs for information. 128*0c4d7b72SSadaf Ebrahimi Another case where buffering is unnecessary is when you write to a 129*0c4d7b72SSadaf Ebrahimi ByteArrayOutputStream since you're writing to memory only. 130*0c4d7b72SSadaf Ebrahimi </p> 131*0c4d7b72SSadaf Ebrahimi </section> 132*0c4d7b72SSadaf Ebrahimi 133*0c4d7b72SSadaf Ebrahimi </body> 134*0c4d7b72SSadaf Ebrahimi 135*0c4d7b72SSadaf Ebrahimi</document> 136