xref: /aosp_15_r20/external/apache-commons-io/src/site/xdoc/bestpractices.xml (revision 0c4d7b72e49a04598d65c566f44504b95342d75a)
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