Q:
|
Regarding relative and absolute path specifications you may
want to read the first three paragraphs of section “File
Systems and Paths” in chapter 16 of [Kurniawan].
Depending on your operating system of choice absolute
(=fully qualified) filenames are being represented
differently:
- Windows:
-
c:\Users\student\Desktop\Downloads.avira_v3.zip
Such path names may be decomposed into:
- UNIX-like (Mac-OS, Linux,...):
-
/usr/share/gpa/gpa-logo.ppm
Possible decomposition:
Implement a class FileMetaInfo to be
instantiated from ordinary strings describing absolute or relative
filenames. Your class shall have several immutable attributes
corresponding to the previously described values. Consider the
following usage example:
public class WindowsExample {
/**
* @param args Unused
*/
public static void main( String[] args ) {
final FileMetaInfo fmi =
new FileMetaInfo("C:\\users\\heinz\\Desktop\\index.html");
System.out.println("Filename is relative? " + fmi.isRelative);
System.out.println("Drive letter:" + fmi.drive);
System.out.println("Directory path: " + fmi.path);
System.out.println("File basename: " + fmi.basename);
System.out.println("File extension: " + fmi.extension);
}
}
On a Windows system the following output is being
expected:
Filename is relative? false
Drive letter:C
Directory path: \users\heinz\Desktop
File basename: index
File extension: html Due to the possible presence of drive letters Windows
pathnames are more difficult to parse. We illustrate a possible
strategy dissecting
C:\programms\openvpn\conf\hdm.ovpn into the
desired constituents:
- Decomposing path components:
-
C:\programms\openvpn\conf\hdm.ovpn
→ {"C:" , "programms" ,
"openvpn" , "conf" ,
"hdm.ovpn" }.
- Drive letter string to character
normalization
-
"C:" → 'C'
- Decomposing filename (if required)
-
"hdm.ovpn" → {"hdm" ,
"ovpn" }
Hints:
-
You will have to deal with absolute and relative (e.g.
../../Desktop/var.png ) filename
specifications.
-
You will have to deal with files having no extensions
like e.g. /usr/bin/firefox . In this case
the extension attribute is expected to be null rather than "" .
-
For the sake of limiting complexity do not consider
filenames starting with a period (like
/home/heinz/.bashrc ) or containing
multiple periods like
../arrow.right.png .
-
To distinguish the above mentioned system defaults for
filename path conventions read the
java.lang.System section of chapter 5
along with its API.
The table of system properties in [Kurniawan] will enable your implementation to
work both on Windows and non-Windows systems
accordingly.
-
Read Java
File Separator vs File Path Separator.
-
You will have to parse filenames like
"/usr/share/openvpn/hdm.conf" . Exercise 7 from
the “Quiz” section of chapter 5 in [Kurniawan] shows an example dissecting a string
containing tokens being separated by space characters using
the java.util.StringTokenizer
class. Read its documentation and learn how to specify string
delimiters other than default space '
' . It'll allow you to dissect paths using separators
'/' (Unix) or '\' (Windows) to break paths into
components.
Likewise you may split filenames into basename /
extension by using '.' as separator.
-
Assembling path components may be effected by either
using a StringBuffer
or a StringJoiner
instance. Mind the distinction between relative and absolute
paths!
-
The methods indexOf(...)
and substring(...)
come in handy when dissecting filenames into basename and
extension.
-
The backslash “\” must be escaped when
being part of a Java™ String
literal:
String path = "C:\\programms\\openvpn\\conf\\hdm.ovpn";
-
Unit tests may be written for Windows and non-Windows
systems separately. Read https://www.thekua.com/atwork/2008/09/running-tests-on-a-specific-os-under-junit4
how to use Assume.assumeFalse() /
Assume.assumeTrue(...) to separate
Windows from Unix tests.
-
Test your implementation both on Windows and Unix-type
platforms. The following tests may be used as a starting
point:
public class MetaInfoUnixTest {
static private final boolean isWindows =
System.getProperty("os.name").startsWith("Windows");
@Test
public void testAbsoluteWithoutExtension() {
Assume.assumeFalse(isWindows);
final FileMetaInfo fmi = new FileMetaInfo("/usr/openvpn/hdm");
Assert.assertFalse(fmi.isRelative);
Assert.assertEquals(FileMetaInfo.noDrive, fmi.drive);
Assert.assertEquals("/usr/openvpn", fmi.path);
Assert.assertEquals("hdm", fmi.basename);
Assert.assertEquals(null, fmi.extension);
}
@Test
public void testAbsoluteWithExtension() {
Assume.assumeFalse(isWindows);
final FileMetaInfo fmi = new FileMetaInfo("/usr/openvpn/hdm.conf");
Assert.assertFalse(fmi.isRelative);
Assert.assertEquals(FileMetaInfo.noDrive, fmi.drive);
Assert.assertEquals("/usr/openvpn", fmi.path);
Assert.assertEquals("hdm", fmi.basename);
Assert.assertEquals("conf", fmi.extension);
}
@Test
public void testRelativeWithoutExtension() {
Assume.assumeFalse(isWindows);
final FileMetaInfo fmi = new FileMetaInfo("../Desktop/icon");
Assert.assertTrue(fmi.isRelative);
Assert.assertEquals(FileMetaInfo.noDrive, fmi.drive);
Assert.assertEquals("../Desktop", fmi.path);
Assert.assertEquals("icon", fmi.basename);
Assert.assertEquals(null, fmi.extension);
}
@Test
public void testRelativeWithExtension() {
Assume.assumeFalse(isWindows);
final FileMetaInfo fmi = new FileMetaInfo("../../Desktop/icon.gif");
Assert.assertTrue(fmi.isRelative);
Assert.assertEquals(FileMetaInfo.noDrive, fmi.drive);
Assert.assertEquals("../../Desktop", fmi.path);
Assert.assertEquals("icon", fmi.basename);
Assert.assertEquals("gif", fmi.extension);
}
}
public class MetaInfoWindowsTest {
static private final boolean isWindows =
System.getProperty("os.name").startsWith("Windows");
@Test
public void testAbsoluteWithoutExtension() {
Assume.assumeTrue(isWindows);
final FileMetaInfo fmi =
new FileMetaInfo("F:\\software\\my\\archive");
Assert.assertFalse(fmi.isRelative);
Assert.assertEquals('F', fmi.drive);
Assert.assertEquals("\\software\\my", fmi.path);
Assert.assertEquals("archive", fmi.basename);
Assert.assertEquals(null, fmi.extension);
}
@Test
public void testAbsoluteWithExtension() {
Assume.assumeTrue(isWindows);
final FileMetaInfo fmi =
new FileMetaInfo("F:\\subdir\\archive.zip");
Assert.assertFalse(fmi.isRelative);
Assert.assertEquals('F', fmi.drive);
Assert.assertEquals("\\subdir", fmi.path);
Assert.assertEquals("archive", fmi.basename);
Assert.assertEquals("zip", fmi.extension);
}
@Test
public void testRelativeWithoutExtension() {
Assume.assumeTrue(isWindows);
final FileMetaInfo fmi = new FileMetaInfo("..\\Desktop\\icon");
Assert.assertTrue(fmi.isRelative);
Assert.assertEquals(FileMetaInfo.noDrive, fmi.drive);
Assert.assertEquals("..\\Desktop", fmi.path);
Assert.assertEquals("icon", fmi.basename);
Assert.assertEquals(null, fmi.extension);
}
@Test
public void testRelativeWithExtension() {
Assume.assumeTrue(isWindows);
final FileMetaInfo fmi =
new FileMetaInfo("..\\..\\Desktop\\icon.gif");
Assert.assertTrue(fmi.isRelative);
Assert.assertEquals(FileMetaInfo.noDrive, fmi.drive);
Assert.assertEquals("..\\..\\Desktop", fmi.path);
Assert.assertEquals("icon", fmi.basename);
Assert.assertEquals("gif", fmi.extension);
}
}
|