Source Code Cross Referenced for FileNameUtil.java in  » Development » jodd » jodd » io » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Development » jodd » jodd.io 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        // Copyright (c) 2003-2007, Jodd Team (jodd.sf.net). All Rights Reserved.
002:
003:        package jodd.io;
004:
005:        import java.io.File;
006:
007:        /**
008:         * General filename and filepath manipulation utilities.
009:         * <p>
010:         * When dealing with filenames you can hit problems when moving from a Windows
011:         * based development machine to a Unix based production machine.
012:         * This class aims to help avoid those problems.
013:         * <p>
014:         * <b>NOTE</b>: You may be able to avoid using this class entirely simply by
015:         * using JDK {@link java.io.File File} objects and the two argument constructor
016:         * {@link java.io.File#File(java.io.File, java.lang.String) File(File,String)}.
017:         * <p>
018:         * Most methods on this class are designed to work the same on both Unix and Windows.
019:         * Those that don't include 'System', 'Unix' or 'Windows' in their name.
020:         * <p>
021:         * Most methods recognise both separators (forward and back), and both
022:         * sets of prefixes. See the javadoc of each method for details.
023:         * <p>
024:         * This class defines six components within a filename
025:         * (example C:\dev\project\file.txt):
026:         * <ul>
027:         * <li>the prefix - C:\</li>
028:         * <li>the path - dev\project\</li>
029:         * <li>the full path - C:\dev\project\</li>
030:         * <li>the name - file.txt</li>
031:         * <li>the base name - file</li>
032:         * <li>the extension - txt</li>
033:         * </ul>
034:         * Note that this class works best if directory filenames end with a separator.
035:         * If you omit the last separator, it is impossible to determine if the filename
036:         * corresponds to a file or a directory. As a result, we have chosen to say
037:         * it corresponds to a file.
038:         * <p>
039:         * This class only supports Unix and Windows style names.
040:         * Prefixes are matched as follows:
041:         * <pre>
042:         * Windows:
043:         * a\b\c.txt           --> ""          --> relative
044:         * \a\b\c.txt          --> "\"         --> current drive absolute
045:         * C:a\b\c.txt         --> "C:"        --> drive relative
046:         * C:\a\b\c.txt        --> "C:\"       --> absolute
047:         * \\server\a\b\c.txt  --> "\\server\" --> UNC
048:         *
049:         * Unix:
050:         * a/b/c.txt           --> ""          --> relative
051:         * /a/b/c.txt          --> "/"         --> absolute
052:         * ~/a/b/c.txt         --> "~/"        --> current user
053:         * ~                   --> "~/"        --> current user (slash added)
054:         * ~user/a/b/c.txt     --> "~user/"    --> named user
055:         * ~user               --> "~user/"    --> named user (slash added)
056:         * </pre>
057:         * Both prefix styles are matched always, irrespective of the machine that you are
058:         * currently running on.
059:         */
060:        public class FileNameUtil {
061:
062:            /**
063:             * The extension separator character.
064:             */
065:            private static final char EXTENSION_SEPARATOR = '.';
066:
067:            /**
068:             * The Unix separator character.
069:             */
070:            private static final char UNIX_SEPARATOR = '/';
071:
072:            /**
073:             * The Windows separator character.
074:             */
075:            private static final char WINDOWS_SEPARATOR = '\\';
076:
077:            /**
078:             * The system separator character.
079:             */
080:            private static final char SYSTEM_SEPARATOR = File.separatorChar;
081:
082:            /**
083:             * The separator character that is the opposite of the system separator.
084:             */
085:            private static final char OTHER_SEPARATOR;
086:            static {
087:                if (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR) {
088:                    OTHER_SEPARATOR = UNIX_SEPARATOR;
089:                } else {
090:                    OTHER_SEPARATOR = WINDOWS_SEPARATOR;
091:                }
092:            }
093:
094:            /**
095:             * Checks if the character is a separator.
096:             */
097:            private static boolean isSeparator(char ch) {
098:                return (ch == UNIX_SEPARATOR) || (ch == WINDOWS_SEPARATOR);
099:            }
100:
101:            // ---------------------------------------------------------------- normalization
102:            /**
103:             * Normalizes a path, removing double and single dot path steps.
104:             * <p>
105:             * This method normalizes a path to a standard format.
106:             * The input may contain separators in either Unix or Windows format.
107:             * The output will contain separators in the format of the system.
108:             * <p>
109:             * A trailing slash will be retained.
110:             * A double slash will be merged to a single slash (but UNC names are handled).
111:             * A single dot path segment will be removed.
112:             * A double dot will cause that path segment and the one before to be removed.
113:             * If the double dot has no parent path segment to work with, <code>null</code>
114:             * is returned.
115:             * <p>
116:             * The output will be the same on both Unix and Windows except
117:             * for the separator character.
118:             * <pre>
119:             * /foo//               -->   /foo/
120:             * /foo/./              -->   /foo/
121:             * /foo/../bar          -->   /bar
122:             * /foo/../bar/         -->   /bar/
123:             * /foo/../bar/../baz   -->   /baz
124:             * //foo//./bar         -->   /foo/bar
125:             * /../                 -->   null
126:             * ../foo               -->   null
127:             * foo/bar/..           -->   foo/
128:             * foo/../../bar        -->   null
129:             * foo/../bar           -->   bar
130:             * //server/foo/../bar  -->   //server/bar
131:             * //server/../bar      -->   null
132:             * C:\foo\..\bar        -->   C:\bar
133:             * C:\..\bar            -->   null
134:             * ~/foo/../bar/        -->   ~/bar/
135:             * ~/../bar             -->   null
136:             * </pre>
137:             * (Note the file separator returned will be correct for Windows/Unix)
138:             *
139:             * @param filename  the filename to normalize, null returns null
140:             * @return the normalized filename, or null if invalid
141:             */
142:            public static String normalize(String filename) {
143:                return doNormalize(filename, true);
144:            }
145:
146:            /**
147:             * Normalizes a path, removing double and single dot path steps,
148:             * and removing any final directory separator.
149:             * <p>
150:             * This method normalizes a path to a standard format.
151:             * The input may contain separators in either Unix or Windows format.
152:             * The output will contain separators in the format of the system.
153:             * <p>
154:             * A trailing slash will be removed.
155:             * A double slash will be merged to a single slash (but UNC names are handled).
156:             * A single dot path segment will be removed.
157:             * A double dot will cause that path segment and the one before to be removed.
158:             * If the double dot has no parent path segment to work with, <code>null</code>
159:             * is returned.
160:             * <p>
161:             * The output will be the same on both Unix and Windows except
162:             * for the separator character.
163:             * <pre>
164:             * /foo//               -->   /foo
165:             * /foo/./              -->   /foo
166:             * /foo/../bar          -->   /bar
167:             * /foo/../bar/         -->   /bar
168:             * /foo/../bar/../baz   -->   /baz
169:             * //foo//./bar         -->   /foo/bar
170:             * /../                 -->   null
171:             * ../foo               -->   null
172:             * foo/bar/..           -->   foo
173:             * foo/../../bar        -->   null
174:             * foo/../bar           -->   bar
175:             * //server/foo/../bar  -->   //server/bar
176:             * //server/../bar      -->   null
177:             * C:\foo\..\bar        -->   C:\bar
178:             * C:\..\bar            -->   null
179:             * ~/foo/../bar/        -->   ~/bar
180:             * ~/../bar             -->   null
181:             * </pre>
182:             * (Note the file separator returned will be correct for Windows/Unix)
183:             *
184:             * @param filename  the filename to normalize, null returns null
185:             * @return the normalized filename, or null if invalid
186:             */
187:            public static String normalizeNoEndSeparator(String filename) {
188:                return doNormalize(filename, false);
189:            }
190:
191:            /**
192:             * Internal method to perform the normalization.
193:             *
194:             * @param filename  the filename
195:             * @param keepSeparator  true to keep the final separator
196:             * @return the normalized filename
197:             */
198:            private static String doNormalize(String filename,
199:                    boolean keepSeparator) {
200:                if (filename == null) {
201:                    return null;
202:                }
203:                int size = filename.length();
204:                if (size == 0) {
205:                    return filename;
206:                }
207:                int prefix = getPrefixLength(filename);
208:                if (prefix < 0) {
209:                    return null;
210:                }
211:
212:                char[] array = new char[size + 2]; // +1 for possible extra slash, +2 for arraycopy
213:                filename.getChars(0, filename.length(), array, 0);
214:
215:                // fix separators throughout
216:                for (int i = 0; i < array.length; i++) {
217:                    if (array[i] == OTHER_SEPARATOR) {
218:                        array[i] = SYSTEM_SEPARATOR;
219:                    }
220:                }
221:
222:                // add extra separator on the end to simplify code below
223:                boolean lastIsDirectory = true;
224:                if (array[size - 1] != SYSTEM_SEPARATOR) {
225:                    array[size] = SYSTEM_SEPARATOR;
226:                    size++;
227:                    lastIsDirectory = false;
228:                }
229:
230:                // adjoining slashes
231:                for (int i = prefix + 1; i < size; i++) {
232:                    if (array[i] == SYSTEM_SEPARATOR
233:                            && array[i - 1] == SYSTEM_SEPARATOR) {
234:                        System.arraycopy(array, i, array, i - 1, size - i);
235:                        size--;
236:                        i--;
237:                    }
238:                }
239:
240:                // dot slash
241:                for (int i = prefix + 1; i < size; i++) {
242:                    if (array[i] == SYSTEM_SEPARATOR
243:                            && array[i - 1] == '.'
244:                            && (i == prefix + 1 || array[i - 2] == SYSTEM_SEPARATOR)) {
245:                        if (i == size - 1) {
246:                            lastIsDirectory = true;
247:                        }
248:                        System.arraycopy(array, i + 1, array, i - 1, size - i);
249:                        size -= 2;
250:                        i--;
251:                    }
252:                }
253:
254:                // double dot slash
255:                outer: for (int i = prefix + 2; i < size; i++) {
256:                    if (array[i] == SYSTEM_SEPARATOR
257:                            && array[i - 1] == '.'
258:                            && array[i - 2] == '.'
259:                            && (i == prefix + 2 || array[i - 3] == SYSTEM_SEPARATOR)) {
260:                        if (i == prefix + 2) {
261:                            return null;
262:                        }
263:                        if (i == size - 1) {
264:                            lastIsDirectory = true;
265:                        }
266:                        int j;
267:                        for (j = i - 4; j >= prefix; j--) {
268:                            if (array[j] == SYSTEM_SEPARATOR) {
269:                                // remove b/../ from a/b/../c
270:                                System.arraycopy(array, i + 1, array, j + 1,
271:                                        size - i);
272:                                size -= (i - j);
273:                                i = j + 1;
274:                                continue outer;
275:                            }
276:                        }
277:                        // remove a/../ from a/../c
278:                        System.arraycopy(array, i + 1, array, prefix, size - i);
279:                        size -= (i + 1 - prefix);
280:                        i = prefix + 1;
281:                    }
282:                }
283:
284:                if (size <= 0) { // should never be less than 0
285:                    return "";
286:                }
287:                if (size <= prefix) { // should never be less than prefix
288:                    return new String(array, 0, size);
289:                }
290:                if (lastIsDirectory && keepSeparator) {
291:                    return new String(array, 0, size); // keep trailing separator
292:                }
293:                return new String(array, 0, size - 1); // lose trailing separator
294:            }
295:
296:            //-----------------------------------------------------------------------
297:            /**
298:             * Concatenates a filename to a base path using normal command line style rules.
299:             * <p>
300:             * The effect is equivalent to resultant directory after changing
301:             * directory to the first argument, followed by changing directory to
302:             * the second argument.
303:             * <p>
304:             * The first argument is the base path, the second is the path to concatenate.
305:             * The returned path is always normalized via {@link #normalize(String)},
306:             * thus <code>..</code> is handled.
307:             * <p>
308:             * If <code>pathToAdd</code> is absolute (has an absolute prefix), then
309:             * it will be normalized and returned.
310:             * Otherwise, the paths will be joined, normalized and returned.
311:             * <p>
312:             * The output will be the same on both Unix and Windows except
313:             * for the separator character.
314:             * <pre>
315:             * /foo/ + bar          -->   /foo/bar
316:             * /foo + bar           -->   /foo/bar
317:             * /foo + /bar          -->   /bar
318:             * /foo + C:/bar        -->   C:/bar
319:             * /foo + C:bar         -->   C:bar (*)
320:             * /foo/a/ + ../bar     -->   foo/bar
321:             * /foo/ + ../../bar    -->   null
322:             * /foo/ + /bar         -->   /bar
323:             * /foo/.. + /bar       -->   /bar
324:             * /foo + bar/c.txt     -->   /foo/bar/c.txt
325:             * /foo/c.txt + bar     -->   /foo/c.txt/bar (!)
326:             * </pre>
327:             * (*) Note that the Windows relative drive prefix is unreliable when
328:             * used with this method.
329:             * (!) Note that the first parameter must be a path. If it ends with a name, then
330:             * the name will be built into the concatenated path. If this might be a problem,
331:             * use {@link #getFullPath(String)} on the base path argument.
332:             *
333:             * @param basePath  the base path to attach to, always treated as a path
334:             * @param fullFilenameToAdd  the filename (or path) to attach to the base
335:             * @return the concatenated path, or null if invalid
336:             */
337:            public static String concat(String basePath,
338:                    String fullFilenameToAdd) {
339:                int prefix = getPrefixLength(fullFilenameToAdd);
340:                if (prefix < 0) {
341:                    return null;
342:                }
343:                if (prefix > 0) {
344:                    return normalize(fullFilenameToAdd);
345:                }
346:                if (basePath == null) {
347:                    return null;
348:                }
349:                int len = basePath.length();
350:                if (len == 0) {
351:                    return normalize(fullFilenameToAdd);
352:                }
353:                char ch = basePath.charAt(len - 1);
354:                if (isSeparator(ch)) {
355:                    return normalize(basePath + fullFilenameToAdd);
356:                } else {
357:                    return normalize(basePath + '/' + fullFilenameToAdd);
358:                }
359:            }
360:
361:            // ---------------------------------------------------------------- separator conversion
362:
363:            /**
364:             * Converts all separators to the Unix separator of forward slash.
365:             *
366:             * @param path  the path to be changed, null ignored
367:             * @return the updated path
368:             */
369:            public static String separatorsToUnix(String path) {
370:                if (path == null || path.indexOf(WINDOWS_SEPARATOR) == -1) {
371:                    return path;
372:                }
373:                return path.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR);
374:            }
375:
376:            /**
377:             * Converts all separators to the Windows separator of backslash.
378:             *
379:             * @param path  the path to be changed, null ignored
380:             * @return the updated path
381:             */
382:            public static String separatorsToWindows(String path) {
383:                if (path == null || path.indexOf(UNIX_SEPARATOR) == -1) {
384:                    return path;
385:                }
386:                return path.replace(UNIX_SEPARATOR, WINDOWS_SEPARATOR);
387:            }
388:
389:            /**
390:             * Converts all separators to the system separator.
391:             *
392:             * @param path  the path to be changed, null ignored
393:             * @return the updated path
394:             */
395:            public static String separatorsToSystem(String path) {
396:                if (path == null) {
397:                    return null;
398:                }
399:                if (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR) {
400:                    return separatorsToWindows(path);
401:                } else {
402:                    return separatorsToUnix(path);
403:                }
404:            }
405:
406:            // ---------------------------------------------------------------- prefix
407:            /**
408:             * Returns the length of the filename prefix, such as <code>C:/</code> or <code>~/</code>.
409:             * <p>
410:             * This method will handle a file in either Unix or Windows format.
411:             * <p>
412:             * The prefix length includes the first slash in the full filename
413:             * if applicable. Thus, it is possible that the length returned is greater
414:             * than the length of the input string.
415:             * <pre>
416:             * Windows:
417:             * a\b\c.txt           --> ""          --> relative
418:             * \a\b\c.txt          --> "\"         --> current drive absolute
419:             * C:a\b\c.txt         --> "C:"        --> drive relative
420:             * C:\a\b\c.txt        --> "C:\"       --> absolute
421:             * \\server\a\b\c.txt  --> "\\server\" --> UNC
422:             *
423:             * Unix:
424:             * a/b/c.txt           --> ""          --> relative
425:             * /a/b/c.txt          --> "/"         --> absolute
426:             * ~/a/b/c.txt         --> "~/"        --> current user
427:             * ~                   --> "~/"        --> current user (slash added)
428:             * ~user/a/b/c.txt     --> "~user/"    --> named user
429:             * ~user               --> "~user/"    --> named user (slash added)
430:             * </pre>
431:             * <p>
432:             * The output will be the same irrespective of the machine that the code is running on.
433:             * ie. both Unix and Windows prefixes are matched regardless.
434:             *
435:             * @param filename  the filename to find the prefix in, null returns -1
436:             * @return the length of the prefix, -1 if invalid or null
437:             */
438:            public static int getPrefixLength(String filename) {
439:                if (filename == null) {
440:                    return -1;
441:                }
442:                int len = filename.length();
443:                if (len == 0) {
444:                    return 0;
445:                }
446:                char ch0 = filename.charAt(0);
447:                if (ch0 == ':') {
448:                    return -1;
449:                }
450:                if (len == 1) {
451:                    if (ch0 == '~') {
452:                        return 2; // return a length greater than the input
453:                    }
454:                    return (isSeparator(ch0) ? 1 : 0);
455:                } else {
456:                    if (ch0 == '~') {
457:                        int posUnix = filename.indexOf(UNIX_SEPARATOR, 1);
458:                        int posWin = filename.indexOf(WINDOWS_SEPARATOR, 1);
459:                        if (posUnix == -1 && posWin == -1) {
460:                            return len + 1; // return a length greater than the input
461:                        }
462:                        posUnix = (posUnix == -1 ? posWin : posUnix);
463:                        posWin = (posWin == -1 ? posUnix : posWin);
464:                        return Math.min(posUnix, posWin) + 1;
465:                    }
466:                    char ch1 = filename.charAt(1);
467:                    if (ch1 == ':') {
468:                        ch0 = Character.toUpperCase(ch0);
469:                        if (ch0 >= 'A' && ch0 <= 'Z') {
470:                            if (len == 2
471:                                    || isSeparator(filename.charAt(2)) == false) {
472:                                return 2;
473:                            }
474:                            return 3;
475:                        }
476:                        return -1;
477:
478:                    } else if (isSeparator(ch0) && isSeparator(ch1)) {
479:                        int posUnix = filename.indexOf(UNIX_SEPARATOR, 2);
480:                        int posWin = filename.indexOf(WINDOWS_SEPARATOR, 2);
481:                        if ((posUnix == -1 && posWin == -1) || posUnix == 2
482:                                || posWin == 2) {
483:                            return -1;
484:                        }
485:                        posUnix = (posUnix == -1 ? posWin : posUnix);
486:                        posWin = (posWin == -1 ? posUnix : posWin);
487:                        return Math.min(posUnix, posWin) + 1;
488:                    } else {
489:                        return (isSeparator(ch0) ? 1 : 0);
490:                    }
491:                }
492:            }
493:
494:            /**
495:             * Returns the index of the last directory separator character.
496:             * <p>
497:             * This method will handle a file in either Unix or Windows format.
498:             * The position of the last forward or backslash is returned.
499:             * <p>
500:             * The output will be the same irrespective of the machine that the code is running on.
501:             *
502:             * @param filename  the filename to find the last path separator in, null returns -1
503:             * @return the index of the last separator character, or -1 if there is no such character
504:             */
505:            public static int indexOfLastSeparator(String filename) {
506:                if (filename == null) {
507:                    return -1;
508:                }
509:                int lastUnixPos = filename.lastIndexOf(UNIX_SEPARATOR);
510:                int lastWindowsPos = filename.lastIndexOf(WINDOWS_SEPARATOR);
511:                return Math.max(lastUnixPos, lastWindowsPos);
512:            }
513:
514:            /**
515:             * Returns the index of the last extension separator character, which is a dot.
516:             * <p>
517:             * This method also checks that there is no directory separator after the last dot.
518:             * To do this it uses {@link #indexOfLastSeparator(String)} which will
519:             * handle a file in either Unix or Windows format.
520:             * <p>
521:             * The output will be the same irrespective of the machine that the code is running on.
522:             *
523:             * @param filename  the filename to find the last path separator in, null returns -1
524:             * @return the index of the last separator character, or -1 if there
525:             * is no such character
526:             */
527:            public static int indexOfExtension(String filename) {
528:                if (filename == null) {
529:                    return -1;
530:                }
531:                int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR);
532:                int lastSeparator = indexOfLastSeparator(filename);
533:                return (lastSeparator > extensionPos ? -1 : extensionPos);
534:            }
535:
536:            // ---------------------------------------------------------------- get
537:
538:            /**
539:             * Gets the prefix from a full filename, such as <code>C:/</code>
540:             * or <code>~/</code>.
541:             * <p>
542:             * This method will handle a file in either Unix or Windows format.
543:             * The prefix includes the first slash in the full filename where applicable.
544:             * <pre>
545:             * Windows:
546:             * a\b\c.txt           --> ""          --> relative
547:             * \a\b\c.txt          --> "\"         --> current drive absolute
548:             * C:a\b\c.txt         --> "C:"        --> drive relative
549:             * C:\a\b\c.txt        --> "C:\"       --> absolute
550:             * \\server\a\b\c.txt  --> "\\server\" --> UNC
551:             *
552:             * Unix:
553:             * a/b/c.txt           --> ""          --> relative
554:             * /a/b/c.txt          --> "/"         --> absolute
555:             * ~/a/b/c.txt         --> "~/"        --> current user
556:             * ~                   --> "~/"        --> current user (slash added)
557:             * ~user/a/b/c.txt     --> "~user/"    --> named user
558:             * ~user               --> "~user/"    --> named user (slash added)
559:             * </pre>
560:             * <p>
561:             * The output will be the same irrespective of the machine that the code is running on.
562:             * ie. both Unix and Windows prefixes are matched regardless.
563:             *
564:             * @param filename  the filename to query, null returns null
565:             * @return the prefix of the file, null if invalid
566:             */
567:            public static String getPrefix(String filename) {
568:                if (filename == null) {
569:                    return null;
570:                }
571:                int len = getPrefixLength(filename);
572:                if (len < 0) {
573:                    return null;
574:                }
575:                if (len > filename.length()) {
576:                    return filename + UNIX_SEPARATOR; // we know this only happens for unix
577:                }
578:                return filename.substring(0, len);
579:            }
580:
581:            /**
582:             * Gets the path from a full filename, which excludes the prefix.
583:             * <p>
584:             * This method will handle a file in either Unix or Windows format.
585:             * The method is entirely text based, and returns the text before and
586:             * including the last forward or backslash.
587:             * <pre>
588:             * C:\a\b\c.txt --> a\b\
589:             * ~/a/b/c.txt  --> a/b/
590:             * a.txt        --> ""
591:             * a/b/c        --> a/b/
592:             * a/b/c/       --> a/b/c/
593:             * </pre>
594:             * <p>
595:             * The output will be the same irrespective of the machine that the code is running on.
596:             * <p>
597:             * This method drops the prefix from the result.
598:             * See {@link #getFullPath(String)} for the method that retains the prefix.
599:             *
600:             * @param filename  the filename to query, null returns null
601:             * @return the path of the file, an empty string if none exists, null if invalid
602:             */
603:            public static String getPath(String filename) {
604:                return doGetPath(filename, 1);
605:            }
606:
607:            /**
608:             * Gets the path from a full filename, which excludes the prefix, and
609:             * also excluding the final directory separator.
610:             * <p>
611:             * This method will handle a file in either Unix or Windows format.
612:             * The method is entirely text based, and returns the text before the
613:             * last forward or backslash.
614:             * <pre>
615:             * C:\a\b\c.txt --> a\b
616:             * ~/a/b/c.txt  --> a/b
617:             * a.txt        --> ""
618:             * a/b/c        --> a/b
619:             * a/b/c/       --> a/b/c
620:             * </pre>
621:             * <p>
622:             * The output will be the same irrespective of the machine that the code is running on.
623:             * <p>
624:             * This method drops the prefix from the result.
625:             * See {@link #getFullPathNoEndSeparator(String)} for the method that retains the prefix.
626:             *
627:             * @param filename  the filename to query, null returns null
628:             * @return the path of the file, an empty string if none exists, null if invalid
629:             */
630:            public static String getPathNoEndSeparator(String filename) {
631:                return doGetPath(filename, 0);
632:            }
633:
634:            /**
635:             * Does the work of getting the path.
636:             *
637:             * @param filename  the filename
638:             * @param separatorAdd  0 to omit the end separator, 1 to return it
639:             * @return the path
640:             */
641:            private static String doGetPath(String filename, int separatorAdd) {
642:                if (filename == null) {
643:                    return null;
644:                }
645:                int prefix = getPrefixLength(filename);
646:                if (prefix < 0) {
647:                    return null;
648:                }
649:                int index = indexOfLastSeparator(filename);
650:                if (prefix >= filename.length() || index < 0) {
651:                    return "";
652:                }
653:                return filename.substring(prefix, index + separatorAdd);
654:            }
655:
656:            /**
657:             * Gets the full path from a full filename, which is the prefix + path.
658:             * <p>
659:             * This method will handle a file in either Unix or Windows format.
660:             * The method is entirely text based, and returns the text before and
661:             * including the last forward or backslash.
662:             * <pre>
663:             * C:\a\b\c.txt --> C:\a\b\
664:             * ~/a/b/c.txt  --> ~/a/b/
665:             * a.txt        --> ""
666:             * a/b/c        --> a/b/
667:             * a/b/c/       --> a/b/c/
668:             * C:           --> C:
669:             * C:\          --> C:\
670:             * ~            --> ~/
671:             * ~/           --> ~/
672:             * ~user        --> ~user/
673:             * ~user/       --> ~user/
674:             * </pre>
675:             * <p>
676:             * The output will be the same irrespective of the machine that the code is running on.
677:             *
678:             * @param filename  the filename to query, null returns null
679:             * @return the path of the file, an empty string if none exists, null if invalid
680:             */
681:            public static String getFullPath(String filename) {
682:                return doGetFullPath(filename, true);
683:            }
684:
685:            /**
686:             * Gets the full path from a full filename, which is the prefix + path,
687:             * and also excluding the final directory separator.
688:             * <p>
689:             * This method will handle a file in either Unix or Windows format.
690:             * The method is entirely text based, and returns the text before the
691:             * last forward or backslash.
692:             * <pre>
693:             * C:\a\b\c.txt --> C:\a\b
694:             * ~/a/b/c.txt  --> ~/a/b
695:             * a.txt        --> ""
696:             * a/b/c        --> a/b
697:             * a/b/c/       --> a/b/c
698:             * C:           --> C:
699:             * C:\          --> C:\
700:             * ~            --> ~
701:             * ~/           --> ~
702:             * ~user        --> ~user
703:             * ~user/       --> ~user
704:             * </pre>
705:             * <p>
706:             * The output will be the same irrespective of the machine that the code is running on.
707:             *
708:             * @param filename  the filename to query, null returns null
709:             * @return the path of the file, an empty string if none exists, null if invalid
710:             */
711:            public static String getFullPathNoEndSeparator(String filename) {
712:                return doGetFullPath(filename, false);
713:            }
714:
715:            /**
716:             * Does the work of getting the path.
717:             *
718:             * @param filename  the filename
719:             * @param includeSeparator  true to include the end separator
720:             * @return the path
721:             */
722:            private static String doGetFullPath(String filename,
723:                    boolean includeSeparator) {
724:                if (filename == null) {
725:                    return null;
726:                }
727:                int prefix = getPrefixLength(filename);
728:                if (prefix < 0) {
729:                    return null;
730:                }
731:                if (prefix >= filename.length()) {
732:                    if (includeSeparator) {
733:                        return getPrefix(filename); // add end slash if necessary
734:                    } else {
735:                        return filename;
736:                    }
737:                }
738:                int index = indexOfLastSeparator(filename);
739:                if (index < 0) {
740:                    return filename.substring(0, prefix);
741:                }
742:                int end = index + (includeSeparator ? 1 : 0);
743:                return filename.substring(0, end);
744:            }
745:
746:            /**
747:             * Gets the name minus the path from a full filename.
748:             * <p>
749:             * This method will handle a file in either Unix or Windows format.
750:             * The text after the last forward or backslash is returned.
751:             * <pre>
752:             * a/b/c.txt --> c.txt
753:             * a.txt     --> a.txt
754:             * a/b/c     --> c
755:             * a/b/c/    --> ""
756:             * </pre>
757:             * <p>
758:             * The output will be the same irrespective of the machine that the code is running on.
759:             *
760:             * @param filename  the filename to query, null returns null
761:             * @return the name of the file without the path, or an empty string if none exists
762:             */
763:            public static String getName(String filename) {
764:                if (filename == null) {
765:                    return null;
766:                }
767:                int index = indexOfLastSeparator(filename);
768:                return filename.substring(index + 1);
769:            }
770:
771:            /**
772:             * Gets the base name, minus the full path and extension, from a full filename.
773:             * <p>
774:             * This method will handle a file in either Unix or Windows format.
775:             * The text after the last forward or backslash and before the last dot is returned.
776:             * <pre>
777:             * a/b/c.txt --> c
778:             * a.txt     --> a
779:             * a/b/c     --> c
780:             * a/b/c/    --> ""
781:             * </pre>
782:             * <p>
783:             * The output will be the same irrespective of the machine that the code is running on.
784:             *
785:             * @param filename  the filename to query, null returns null
786:             * @return the name of the file without the path, or an empty string if none exists
787:             */
788:            public static String getBaseName(String filename) {
789:                return removeExtension(getName(filename));
790:            }
791:
792:            /**
793:             * Gets the extension of a filename.
794:             * <p>
795:             * This method returns the textual part of the filename after the last dot.
796:             * There must be no directory separator after the dot.
797:             * <pre>
798:             * foo.txt      --> "txt"
799:             * a/b/c.jpg    --> "jpg"
800:             * a/b.txt/c    --> ""
801:             * a/b/c        --> ""
802:             * </pre>
803:             * <p>
804:             * The output will be the same irrespective of the machine that the code is running on.
805:             *
806:             * @param filename the filename to retrieve the extension of.
807:             * @return the extension of the file or an empty string if none exists.
808:             */
809:            public static String getExtension(String filename) {
810:                if (filename == null) {
811:                    return null;
812:                }
813:                int index = indexOfExtension(filename);
814:                if (index == -1) {
815:                    return "";
816:                } else {
817:                    return filename.substring(index + 1);
818:                }
819:            }
820:
821:            //----------------------------------------------------------------------- remove
822:
823:            /**
824:             * Removes the extension from a filename.
825:             * <p>
826:             * This method returns the textual part of the filename before the last dot.
827:             * There must be no directory separator after the dot.
828:             * <pre>
829:             * foo.txt    --> foo
830:             * a\b\c.jpg  --> a\b\c
831:             * a\b\c      --> a\b\c
832:             * a.b\c      --> a.b\c
833:             * </pre>
834:             * <p>
835:             * The output will be the same irrespective of the machine that the code is running on.
836:             *
837:             * @param filename  the filename to query, null returns null
838:             * @return the filename minus the extension
839:             */
840:            public static String removeExtension(String filename) {
841:                if (filename == null) {
842:                    return null;
843:                }
844:                int index = indexOfExtension(filename);
845:                if (index == -1) {
846:                    return filename;
847:                } else {
848:                    return filename.substring(0, index);
849:                }
850:            }
851:
852:            // ---------------------------------------------------------------- equals
853:
854:            /**
855:             * Checks whether two filenames are equal exactly.
856:             */
857:            public static boolean equals(String filename1, String filename2) {
858:                return equals(filename1, filename2, false);
859:            }
860:
861:            /**
862:             * Checks whether two filenames are equal using the case rules of the system.
863:             */
864:            public static boolean equalsOnSystem(String filename1,
865:                    String filename2) {
866:                return equals(filename1, filename2, true);
867:            }
868:
869:            /**
870:             * Checks whether two filenames are equal optionally using the case rules of the system.
871:             * <p>
872:             *
873:             * @param filename1  the first filename to query, may be null
874:             * @param filename2  the second filename to query, may be null
875:             * @param system  whether to use the system (windows or unix)
876:             * @return true if the filenames are equal, null equals null
877:             */
878:            private static boolean equals(String filename1, String filename2,
879:                    boolean system) {
880:                //noinspection StringEquality
881:                if (filename1 == filename2) {
882:                    return true;
883:                }
884:                if (filename1 == null || filename2 == null) {
885:                    return false;
886:                }
887:                if (system && (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR)) {
888:                    return filename1.equalsIgnoreCase(filename2);
889:                } else {
890:                    return filename1.equals(filename2);
891:                }
892:            }
893:
894:            // ---------------------------------------------------------------- split
895:
896:            /**
897:             * Splits filename into a array of four Strings containing prefix, path, basename and extension.
898:             * Path will contain ending separator.
899:             */
900:            public static String[] split(String filename) {
901:                String prefix = getPrefix(filename);
902:                if (prefix == null) {
903:                    prefix = "";
904:                }
905:                int lastSeparatorIndex = indexOfLastSeparator(filename);
906:                int lastExtensionIndex = indexOfExtension(filename);
907:
908:                String path;
909:                String baseName;
910:                String extension;
911:
912:                if (lastSeparatorIndex == -1) {
913:                    path = "";
914:                    if (lastExtensionIndex == -1) {
915:                        baseName = filename.substring(prefix.length());
916:                        extension = "";
917:                    } else {
918:                        baseName = filename.substring(prefix.length(),
919:                                lastExtensionIndex);
920:                        extension = filename.substring(lastExtensionIndex + 1);
921:                    }
922:                } else {
923:                    path = filename.substring(prefix.length(),
924:                            lastSeparatorIndex + 1);
925:                    if (lastExtensionIndex == -1) {
926:                        baseName = filename.substring(prefix.length()
927:                                + path.length());
928:                        extension = "";
929:                    } else {
930:                        baseName = filename.substring(prefix.length()
931:                                + path.length(), lastExtensionIndex);
932:                        extension = filename.substring(lastExtensionIndex + 1);
933:                    }
934:                }
935:                return new String[] { prefix, path, baseName, extension };
936:            }
937:
938:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.