Files in Groovy

To see the OS-dependent characters used for formatting filenames (here, when running on Windows):

assert File.separator == '\\' && File.separatorChar == '\\' as char //used for formatting file names
assert File.pathSeparator == ';' && File.pathSeparatorChar == ';' as char

Instances of File are immutable representations of objects in the file system, that may or may not exist. To see different formats of a filename:

def f= new File('File.txt') //relative file name
assert f.name == 'File.txt'
assert ! f.isAbsolute()
assert f.path == 'File.txt'
assert f.parent == null

def dir= 'C:\\Users\\gavin\\Documents\\Personal\\Doco\\'
def dirParent= 'C:\\Users\\gavin\\Documents\\Personal\\'
def dirCurrent= 'Doco\\'

assert f.absolutePath == dir + 'File.txt' //returns a string
assert f.absoluteFile.toString() == dir + 'File.txt' //returns a File object instead of string
assert f.canonicalPath == dir + 'File.txt'
assert f.canonicalFile.toString() == dir + 'File.txt' //returns a File object instead of string
assert f.toURI().toString() == 'file:/C:/Users/gavin/Documents/Personal/Doco/File.txt' //toURI() returns a URI object

f= new File(dir + 'File.txt') //absolute file name
assert f.name == 'File.txt'
assert f.isAbsolute()
assert f.path == dir + 'File.txt'
assert f.parent == dir[0..-2]

assert f.parentFile.toString() == dir[0..-2] //returns a File object instead of string
assert f.absolutePath == dir + 'File.txt'
assert f.canonicalPath == dir + 'File.txt'

f= new File('../File.txt')
assert f.name == 'File.txt'
assert ! f.isAbsolute()
assert f.path == '..\\File.txt'
assert f.parent == '..'
assert f.absolutePath == dir + '..\\File.txt'
assert f.canonicalPath == dirParent + 'File.txt'

f= new File('') //current directory
assert f.name == ''
assert ! f.isAbsolute()
assert f.path == ''
assert f.parent == null
assert f.absolutePath == dir[0..-2]
assert f.canonicalPath == dir[0..-2]

assert new File('File.txt') == new File('File.txt') //compares two filenames' lexical names
assert new File('File.txt').compareTo(new File('File.txt')) == 0 //equivalent method name
assert new File('File.txt') != new File('../' + dirCurrent + 'File.txt') //lexical names different (although files are the same)

None of the above example's files were created. Files are only created by some event:

def f1= new File('File1.txt')
f1 << 'abcdefg' //file created by writing to it; file appended to if it already exists
assert f1.length() == 7 && f1.size() == 7
assert f1.isFile() && ! f1.isDirectory() && ! f1.isHidden()

def dir= 'C:\\Users\\gavin\\Documents\\Personal\\Doco\\'
def f2= new File(dir, 'File2.txt') //we can optionally supply the parent, either as a string...
f2= new File(new File(dir), 'File2.txt') //...or as a File object
assert ! f2.exists()
f2.createNewFile() //if it doesn't already exist
assert f2.exists()

def d1= new File('Directory1')
d1.mkdir() //make directory, if it doesn't already exist
def d2= new File('Directory2/SubDir1')
d2.mkdirs() //make directory, including necessary but nonexistent parent directories

println f1.getFreeSpace() //the number of unallocated bytes in the partition this abstract file is in
println f1.getUsableSpace() //the number of bytes available to this virtual machine in the partition this abstract file is in
println f1.getTotalSpace() //the size of the partition this abstract file is in

//We can set file permissions:
assert f2.setWritable(true, false) && f2.canWrite() //set writable permission for every user
assert f2.setWritable(true) && f2.canWrite() //set writable permission on file for owner only
assert f2.setWritable(false, false) && ! f2.canWrite()  //unset writable permission for every user
assert f2.setWritable(false) && ! f2.canWrite() //unset writable permission on file for owner only
f2.writable= true //property format for owner only
assert f2.canWrite()

assert f2.setReadOnly() && ! f2.canWrite()
assert f2.setExecutable(true, false) && f2.canExecute() //set executable permission for every user
assert f2.setExecutable(true) && f2.canExecute() //set executable permission on file for owner only
f2.executable= true //property format for owner only
assert f2.canExecute()
assert ! f2.setExecutable(false)
  //returns false because command unsuccessful: can't make file nonexecutable on Windows, though can on other systems

assert f2.setReadable(true, false) && f2.canRead() //set readable permission for every user
assert f2.setReadable(true) && f2.canRead() //set readable permission on file for owner only
f2.readable= true //property format for owner only
assert f2.canRead()
assert ! f2.setReadable(false) //can't make file nonreadable on Windows

//We can retrieve a list of files from a directory:
['File1.txt', 'File2.txt', 'Directory1', 'Directory2'].each{
  assert it in new File(dir).list().toList() //list() returns an array of strings
}
assert new File('Directory2').list().toList() == ['SubDir1']
assert new File('').list() == null //list() returns null if directory not explicitly specified

['File1.txt', 'Directory1'].each{ //filter taking dir (File) and file (String) arguments, returns boolean
  assert it in new File(dir).list( [accept:{d, f-> f ==~ /.*?1.*/ }] as FilenameFilter ).toList()
  assert it in new File(dir).list({d, f-> f ==~ /.*?1.*/ } as FilenameFilter).toList() //shorter syntax
}

['File1.txt', 'File2.txt', 'Directory1', 'Directory2'].each{
  assert it in new File(dir).listFiles().toList()*.name //listFiles() returns array of File objects
}  

assert new File('Directory2').listFiles().toList()*.toString() == ['Directory2\\SubDir1']

[ 'File1.txt', 'File2.txt' ].each{
  assert it in new File(dir).listFiles( {directory, file-> file ==~ /.*?\.txt/ } as FilenameFilter ).toList()*.name
}

[ 'File1.txt', 'File2.txt' ].each{
  assert it in new File(dir).listFiles( [accept:{file-> file ==~ /.*?\.txt/ }] as FileFilter ).toList()*.name
} //use a filter taking one argument only, returning boolean

//Renaming and deleting files:

f2.renameTo( new File('RenamedFile2.txt') )
assert f2.name == 'File2.txt' //because File object is immutable
assert new File('RenamedFile2.txt').exists()

[new File('RenamedFile2.txt'), new File('Directory1'), new File('Directory2')].each{ it.delete() } //delete files
assert ! new File('RenamedFile2.txt').exists()
assert ! new File('Directory1').exists()
assert new File('Directory2').exists() //because each sub-directory must be deleted separately

assert new File('Directory2/SubDir1').delete() //returns true if file deleted OK
assert new File('Directory2').delete()
assert ! new File('Directory2').exists()

new File('File1.txt').deleteOnExit()
assert new File('File1.txt').exists() //but will be deleted when VM exits

def mod= new File('File1.txt').lastModified()
assert new File('File1.txt').setLastModified(mod - 60000) //60 seconds previously, returns true if successful
new File('File1.txt').lastModified= mod - 120000 //property syntax for setting only
assert new File('File1.txt').lastModified() == mod - 120000

To perform general file manipulation in a file system, we can retrieve all the topmost directories:
println File.listRoots().toList()*.toString() //listRoots() returns an array of File objects

To create a temporary file, with given prefix (of at least 3 chars) and suffix:

def dir= 'C:\\Users\\gavin\\Documents\\Personal\\Doco\\'
File.createTempFile('Tem', '.txt') //created in directory for temporary files
File.createTempFile('Tem', '.txt', new File(dir)) //created in current directory

We can read and write to files in various ways, as in this example:

def dir= 'C:\\Users\\gavin\\Documents\\Personal\\Doco\\'

def f1= new File('NewFile1.txt') << 'abcdefg:hijklmnop:qrstuv:wxyz\n' //create and write to the file
f1.leftShift('123:456:7890\n') //equivalent method name
new File('File2.txt').createNewFile()
[new File('Directory1'), new File('Directory2/SubDir1')].each{ it.mkdirs() }

def list= []
new File(dir).eachFile{ list<< it.name } //eachFile() returns a list of File objects
['NewFile1.txt', 'File2.txt', 'Directory1', 'Directory2'].each{
  assert it in list
}

list= []
new File(dir).eachFileMatch(~/.*?File.*?\.txt/){ list<< it.name } //a regular expression, or any caseable expression
['NewFile1.txt', 'File2.txt'].each{
  assert it in list
}

list= []
new File(dir).eachFileRecurse{ list<< it.name }
['NewFile1.txt', 'File2.txt', 'Directory1', 'Directory2', 'SubDir1'].each{
  assert it in list
}

list= []
new File(dir).eachDir{ list<< it.name }
['Directory1', 'Directory2'].each{
  assert it in list
}

list= []
f1.eachLine{ list<< it }
assert list == [ 'abcdefg:hijklmnop:qrstuv:wxyz', '123:456:7890' ]

list= f1.readLines()
assert list == [ 'abcdefg:hijklmnop:qrstuv:wxyz', '123:456:7890' ]

list= []
f1.splitEachLine(':'){ list<< it } //splits each line into a list
assert list == [
  ['abcdefg', 'hijklmnop', 'qrstuv', 'wxyz'],
  ['123', '456', '7890'],
]

def f2= new File('File2.txt')
f2.write('abcdefg\n') //can only write strings
assert f2.getText() == 'abcdefg\n'
f2.append('hijklmnop,')
f2.append(42) //can append any object
assert f2.getText() == '''abcdefg
hijklmnop,42'''

f2.write('一二三四五', 'unicode') //overwrites existing contents
assert f2.getText('unicode') == '一二三四五'
f2.append('六七八九十', 'unicode') //also appends unicode marker 0xFEFF
assert f2.getText('unicode') == '一二三四五' + (0xFEFF as char) + '六七八九十'

[ new File('NewFile1.txt'),
  new File('File2.txt'),
  new File('Directory1'),
  new File('Directory2/SubDir1'),
  new File('Directory2'),
].each{ it.delete() } //delete files used by this example

Last edited Feb 1, 2011 at 1:01 PM by gavingrover, version 1

Comments

No comments yet.