package javaxt.io; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.io.*; import java.util.Locale; //****************************************************************************** //** File Class //****************************************************************************** /** * Used to represent a single file on a file system. In many ways, this class * is an extension of the java.io.File class. However, unlike the java.io.File * class, this object provides functions that are relevant and specific to * files (not directories). * ******************************************************************************/ public class File implements Comparable { private java.io.File file; //<--DO NOT USE DIRECTLY! Use getFile() instead. private String name = ""; private String path = ""; private FileAttributes attr; private long lastAttrUpdate = 0; public final String PathSeparator = System.getProperty("file.separator"); public final String LineSeperator = System.getProperty("line.separator"); private static final boolean isWindows = Directory.isWindows; private int bufferSize = 1024*1024; //1MB //public static final boolean jni = loadDLL(); //************************************************************************** //** Constructor //************************************************************************** /** Creates a new File instance by converting the given pathname string into * an abstract pathname. */ public File(String Path) { if (Path == null) { throw new NullPointerException(); } if (Path.startsWith("\"") && Path.endsWith("\"")){ Path = Path.substring(1,Path.length()-1).trim(); } if (Path.endsWith("\\") || Path.endsWith("/")){ throw new IllegalArgumentException("Invalid Path: " + Path); } init(Path); //int idx = Path.replace("\\", "/").lastIndexOf("/")+1; //path = Path.substring(0, idx); //name = Path.substring(idx); } //************************************************************************** //** Constructor //************************************************************************** /** Instantiates this class using a java.io.File. Please use the Directory * class for directories. Example: *
if (file.isDirectory()) new Directory(file);*/ public File(java.io.File File) { if (File==null) { throw new NullPointerException(); } if (File.isDirectory()){ throw new IllegalArgumentException("Invalid Path."); } String p = File.getAbsolutePath(); init(p); if (p.equals(toString())){ this.file = File; } } //************************************************************************** //** Constructor //************************************************************************** /** Creates a new File instance from a parent abstract pathname and a child * pathname string. */ public File(java.io.File Parent, String Child){ this(Parent.getPath(), Child); } public File(Directory Parent, String Child){ this(Parent.getPath(), Child); } public File(String Parent, String Child){ if (Parent == null || Child == null) { throw new NullPointerException(); } //Normalize the strings Parent = Parent.replace("\\", "/"); Child = Child.replace("\\", "/"); //Combine the Parent and Child into a single path. This is done in //case the Child variable contains additional path information. if (!Parent.endsWith("/")) Parent += "/"; if (Child.startsWith("/")) Child = Child.substring(1); if (Child.endsWith("/")) Child = Child.substring(0, Child.length()-1); init(Parent + Child); } /** Used to parse the absolute path to the file. For performance reasons, * we do not rely on the java.io.File to determine the path and name * variables. */ private void init(String Path){ Path = Path.replace("\\", "/"); String[] arr = Path.split("/"); if (arr.length>1){ name = arr[arr.length-1]; path = Path.substring(0, Path.lastIndexOf(name)); } else{ name = arr[0]; path = "./"; } if (path.isEmpty()) path = PathSeparator; else path = path.replace("/", PathSeparator); if (!path.endsWith(PathSeparator)) path += PathSeparator; //Special case for relative paths if (path.startsWith(".")){ try{ init(new java.io.File(path + name).getCanonicalPath()); } catch(Exception e){ throw new IllegalArgumentException("Invalid Path."); } } } //************************************************************************** //** Get File Name //************************************************************************** /** Returns the name of the file, excluding the path. */ public String getName(){ return name; } //************************************************************************** //** Get File Name //************************************************************************** /** Returns the name of the file, excluding the path. * * @param IncludeFileExtension If true, includes the file extension. * Otherwise, will return the file name without the extension. */ public String getName(boolean IncludeFileExtension){ if (!IncludeFileExtension){ int idx = name.lastIndexOf("."); if (idx > -1) return name.substring(0, idx); } return name; } //************************************************************************** //** Get File Path //************************************************************************** /** Used to retrieve the path to the file, excluding the file name. Appends * a file separator to the end of the string. */ public String getPath(){ return path; } //************************************************************************** //** Get Directory //************************************************************************** /** Returns the file's parent directory. Same as getParentDirectory() */ public Directory getDirectory(){ return getParentDirectory(); } //************************************************************************** //** Get Parent Directory //************************************************************************** /** Returns the file's parent directory. Returns null if the parent * directory is unknown. */ public Directory getParentDirectory(){ if (path.length()>0) return new Directory(path); else return null; } //************************************************************************** //** toFile //************************************************************************** /** Returns the java.io.File representation of this object. */ public java.io.File toFile(){ return getFile(); } //************************************************************************** //** getFile //************************************************************************** /** Returns the java.io.File representation of this object. */ private java.io.File getFile(){ if (file==null) file = new java.io.File(path + name); return file; } //************************************************************************** //** Get File Extension //************************************************************************** /** Returns the file's extension, excluding the last dot/period * (e.g. "C:\image.jpg" will return "jpg"). Returns a zero-length string * if there is no extension. */ public String getExtension(){ int idx = name.lastIndexOf("."); if (idx > -1) return name.substring(idx+1); else return ""; } //************************************************************************** //** getSize //************************************************************************** /** Returns the size of the file, in bytes. Returns 0L if the file is does * not exist or if the object is a directory. */ public long getSize(){ if (file!=null) return getFileSize(); try{ FileAttributes attr = getFileAttributes(); if (attr!=null) return attr.getSize(); else{ getFile(); return getFileSize(); } } catch(java.io.FileNotFoundException e){ return 0L; } } private long getFileSize(){ long size = file.length(); if (size>0L && file.isFile()) return size; else return 0L; } //************************************************************************** //** getDate //************************************************************************** /** Returns a timestamp of when the file was last modified. Returns null if * the file does not exist or if the object is a directory. */ public java.util.Date getDate(){ if (file!=null) return getFileDate(); try{ FileAttributes attr = getFileAttributes(); if (attr!=null) return attr.getLastWriteTime(); else{ getFile(); return getFileDate(); } } catch(java.io.FileNotFoundException e){ return null; } } private java.util.Date getFileDate(){ if (file.exists() && file.isFile()) return new java.util.Date(file.lastModified()); else return null; } //************************************************************************** //** setDate //************************************************************************** /** Used to set/update the last modified date. */ public boolean setDate(java.util.Date lastModified){ if (lastModified!=null){ java.io.File file = getFile(); if (file.exists() && file.isFile()){ long t = lastModified.getTime(); if (getDate().getTime()!=t){ attr = null; return getFile().setLastModified(t); } } } return false; } //************************************************************************** //** Exists //************************************************************************** /** Used to determine whether a file exists. Returns false if the file * system can't find the file or if the object is a directory. */ public boolean exists(){ if (file!=null){ return (file.isFile() && file.exists()); } try{ FileAttributes attr = getFileAttributes(); if (attr!=null) return true; else{ getFile(); return (file.isFile() && file.exists()); } } catch(java.io.FileNotFoundException e){ return false; } } //************************************************************************** //** isHidden //************************************************************************** /** Used to check whether the file is hidden. Returns true if the file * exists and is hidden according to the conventions of the underlying * file system. */ public boolean isHidden(){ if (file!=null){ return (file.isFile() && file.isHidden()); } try{ FileAttributes attr = getFileAttributes(); if (attr!=null) return attr.isHidden(); else{ getFile(); return (file.isFile() && file.isHidden()); } } catch(java.io.FileNotFoundException e){ return false; } } //************************************************************************** //** isReadOnly //************************************************************************** /** Used to check whether the file has write permissions. Returns true if * the file exists and the application is not allowed to write to the file. */ public boolean isReadOnly(){ if (file!=null){ return (file.isFile() && !file.canWrite()); } try{ FileAttributes attr = getFileAttributes(); if (attr!=null) return attr.isReadOnly(); else{ getFile(); return (file.isFile() && !file.canWrite()); } } catch(java.io.FileNotFoundException e){ return false; } } //************************************************************************** //** isExecutable //************************************************************************** /** Used to check whether the file has execute permissions. Note that this * method is not supported by JDK 1.5 or lower. Instead, the method will * return false. */ public boolean isExecutable(){ java.io.File File = getFile(); if (File!=null){ //return File.canExecute(); //<--incompatable with JDK 1.5 int javaVersion = javaxt.utils.Java.getVersion(); if (javaVersion<6) return false; else{ try{ return (Boolean) File.getClass().getMethod("canExecute").invoke(File, null); } catch(Exception e){ return false; } } } else return false; } //************************************************************************** //** isLink //************************************************************************** /** Used to determine whether the file is actually a link to another file. * Returns true for symbolic links, Windows junctions, and Windows * shortcuts. */ public boolean isLink(){ return getLink()!=null; } //************************************************************************** //** getLink //************************************************************************** /** Returns the target of a symbolic link, Windows junction, or Windows * shortcut. */ public java.io.File getLink(){ try{ return getFileAttributes().getLink(); } catch(Exception e){ return null; } } //************************************************************************** //** Delete File //************************************************************************** /** Used to delete the file. Warning: this operation is irrecoverable. */ public boolean delete(){ java.io.File file = getFile(); if (file!=null){ if (file.delete()){ attr=null; return true; } } return false; } //************************************************************************** //** setBufferSize //************************************************************************** /** Used to set the size of the buffer used to read/write bytes. The default * is 1MB (1,048,576 bytes) */ public void setBufferSize(int numBytes){ bufferSize = numBytes; } //************************************************************************** //** Move File //************************************************************************** /** Used to move the file to a different directory. If the operation is * successful, returns a handle to the new file. Otherwise, the original * file is returned. */ public javaxt.io.File moveTo(Directory Destination){ return moveTo(new javaxt.io.File(Destination, getName()), true); } //************************************************************************** //** Move File //************************************************************************** /** Used to move the file to a different location. If the operation is * successful, returns a handle to the new file. Otherwise, the original * file is returned. */ public javaxt.io.File moveTo(javaxt.io.File Destination, boolean Overwrite){ if (Destination.exists()){ if (Overwrite){ Destination.delete(); } else{ return this; } } java.io.File oldFile = getFile(); java.io.File newFile = Destination.toFile(); newFile.getParentFile().mkdirs(); if (oldFile.renameTo(newFile)){ attr = null; file = newFile; init(file.getAbsolutePath()); } return this; } //************************************************************************** //** Copy File //************************************************************************** /** Used to create a copy of this file. Preserves the last modified date * associated with the source file. Returns true if the file was copied * successfully. */ public boolean copyTo(Directory Destination, boolean Overwrite){ return copyTo(new File(Destination, getName()), Overwrite); } //************************************************************************** //** Copy File //************************************************************************** /** Used to create a copy of this file. Preserves the last modified date * associated with the source file. Returns true if the file was copied * successfully. */ public boolean copyTo(javaxt.io.File Destination, boolean Overwrite){ //Validate Input/Output java.io.File File = getFile(); if (File.exists()==false) return false; if (Destination.exists() && Overwrite==false) return false; if (File.equals(Destination.toFile())) return false; //Create New Path Destination.getParentDirectory().create(); //Copy File ReadableByteChannel inputChannel = null; WritableByteChannel outputChannel = null; try{ FileInputStream input = new FileInputStream(File); FileOutputStream output = new FileOutputStream(Destination.toFile()); inputChannel = Channels.newChannel(input); outputChannel = Channels.newChannel(output); final java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocateDirect(bufferSize); while (inputChannel.read(buffer) != -1) { buffer.flip(); outputChannel.write(buffer); buffer.compact(); } buffer.flip(); while (buffer.hasRemaining()) { outputChannel.write(buffer); } inputChannel.close(); outputChannel.close(); Destination.toFile().setLastModified(File.lastModified()); return true; } catch(Exception e){ try{inputChannel.close();}catch(Exception ex){} try{outputChannel.close();}catch(Exception ex){} return false; } } //************************************************************************** //** Rename File //************************************************************************** /** Used to rename the file. The existing file name is replaced with a new * name. Only the file name is affected. The file path remains unchanged. * This method is therefore different from the java.io.File "renameTo" * method. If the operation is successful, returns a handle to the new file. * Otherwise, the original file is returned. * @param FileName The new file name (including the file extension). */ public javaxt.io.File rename(String FileName){ if (FileName!=null){ FileName = FileName.trim(); if (FileName.length()>0){ java.io.File File = getFile(); if (File!=null) { java.io.File newFile = new java.io.File(getPath() + FileName); if (File.renameTo(newFile)){ attr = null; file = newFile; init(file.getAbsolutePath()); } } } } return this; } //************************************************************************** //** getBufferedWriter //************************************************************************** /** Used to instantiate a BufferedWriter for this file. */ public BufferedWriter getBufferedWriter(String charsetName){ try{ java.io.File File = getFile(); attr = null; File.getParentFile().mkdirs(); if (charsetName==null){ return new BufferedWriter( new FileWriter(File) ); } else{ return new BufferedWriter(new OutputStreamWriter(new FileOutputStream(File), charsetName)); } } catch (Exception e){ return null; } } //************************************************************************** //** getBufferedReader //************************************************************************** /** Used to extract the contents of the file into a BufferedReader.
BufferedReader br = file.getBufferedReader("UTF-8");
String strLine;
while ((strLine = br.readLine()) != null){
System.out.println(strLine);
}
* @return BufferedReader or null
*/
public BufferedReader getBufferedReader(){
java.io.File File = getFile();
if (File.exists()){
try{
//NOTE: FileReader always assumes default encoding is OK!
return new BufferedReader( new FileReader(File) );
}
catch (Exception e){
}
}
return null;
}
//**************************************************************************
//** getBufferedReader
//**************************************************************************
/** Used to extract the contents of the file into a BufferedReader.
BufferedReader br = file.getBufferedReader("UTF-8");
String strLine;
while ((strLine = br.readLine()) != null){
System.out.println (strLine);
}
* WARNING: This method will never throw an error.
*
* @param charsetName Name of the character encoding used to read the file.
* Examples include UTF-8 and ISO-8859-1
*/
public BufferedReader getBufferedReader(String charsetName){
java.io.File File = getFile();
if (File.exists()){
try{
return new java.io.BufferedReader(new java.io.InputStreamReader(this.getInputStream(),charsetName));
}
catch (Exception e){
}
}
return null;
}
//**************************************************************************
//** getBufferedImage
//**************************************************************************
/** Returns the file contents as a BufferedImage. Returns a null if the file
* contents cannot be converted into a BufferedImage.
*/
public java.awt.image.BufferedImage getBufferedImage(){
Image img = getImage();
if (img!=null) return img.getBufferedImage();
return null;
}
//**************************************************************************
//** getImage
//**************************************************************************
/** Returns the file contents as an Image (javaxt.io.Image). Returns a null
* if the file contents cannot be converted into an Image.
*/
public Image getImage(){
java.io.File File = getFile();
if (File.exists()) return new Image(File);
else return null;
}
//**************************************************************************
//** getText
//**************************************************************************
/** Returns the file contents as a String. Returns an empty String if the
* file is empty or the contents cannot be converted to a String.
*/
public String getText(){
try{
return getText("UTF-8");
}
catch(Exception e){}
try{
return getBytes().toString();
}
catch(Exception e){}
return "";
}
//**************************************************************************
//** getText
//**************************************************************************
/** Returns the file contents as a String. Returns an empty String if the
* file is empty or the contents cannot be converted to a String.
* @param charsetName Name of the character encoding used to read the file.
* Examples include UTF-8 and ISO-8859-1
*/
public String getText(String charsetName){
try{
return getBytes().toString(charsetName);
}
catch(Exception e){}
return "";
}
//**************************************************************************
//** getXML
//**************************************************************************
/** Returns the file contents as a XML DOM Document(org.w3c.dom.Document).
* Returns a null if the file contents cannot be converted into a DOM
* Document.
*/
public org.w3c.dom.Document getXML(){
try (FileInputStream is = getInputStream()) {
return javaxt.xml.DOM.createDocument(is);
}
catch(Exception e){
return null;
}
}
//**************************************************************************
//** getJSONObject
//**************************************************************************
/** Returns the file contents as a JSON object (javaxt.json.JSONObject).
* Returns a null if the file contents cannot be converted into a JSON
* object.
*/
public javaxt.json.JSONObject getJSONObject(){
try {
return new javaxt.json.JSONObject(getText());
}
catch(Exception e){
return null;
}
}
//**************************************************************************
//** getJSONArray
//**************************************************************************
/** Returns the file contents as a JSON array (javaxt.json.JSONArray).
* Returns a null if the file contents cannot be converted into a JSON
* array.
*/
public javaxt.json.JSONArray getJSONArray(){
try {
return new javaxt.json.JSONArray(getText());
}
catch(Exception e){
return null;
}
}
//**************************************************************************
//** getBytes
//**************************************************************************
/** Returns the file contents as a ByteArrayOutputStream. Returns a null if
* the file contents cannot be converted to a ByteArrayOutputStream.
*/
public ByteArrayOutputStream getBytes(){
return getBytes(getFile(), bufferSize);
}
private static ByteArrayOutputStream getBytes(java.io.File File, int bufferSize){
if (File.exists()){
try (FileInputStream is = new FileInputStream(File)) {
ByteArrayOutputStream bas = new ByteArrayOutputStream();
byte[] b = new byte[bufferSize];
int x;
while((x=is.read(b,0,bufferSize))>-1) {
bas.write(b,0,x);
}
bas.close();
return bas;
}
catch(Exception e){
}
}
return null;
}
//**************************************************************************
//** checksum
//**************************************************************************
/** Returns a long value representing a cyclic redundancy check
* (CRC-32 checksum) of the file, or -1 if not known.
*/
public long checksum(){
if (!exists()) return -1;
try{
java.util.zip.CRC32 crc = new java.util.zip.CRC32();
crc.update(getBytes().toByteArray());
return crc.getValue();
}
catch(Exception e){
return -1;
}
}
//**************************************************************************
//** getSHA1
//**************************************************************************
/** Returns a string representing the SHA-1 hash for the file.
*/
public String getSHA1() {
return getHash("SHA-1");
}
//**************************************************************************
//** getMD5
//**************************************************************************
/** Returns a string representing the MD5 hash for the file.
*/
public String getMD5() {
return getHash("MD5");
}
//**************************************************************************
//** getHash
//**************************************************************************
private String getHash(String algorithm){
if (!exists()) return null;
try (InputStream input = getInputStream()) {
java.security.MessageDigest md = java.security.MessageDigest.getInstance(algorithm);
byte[] buf = new byte[bufferSize];
int i;
while((i=input.read(buf))!=-1) {
md.update(buf, 0, i);
}
//return new javax.xml.bind.annotation.adapters.HexBinaryAdapter().marshal(md.digest()).toLowerCase();
return printHexBinary(md.digest()).toLowerCase();
}
catch(Exception e){
return null;
}
}
private static final char[] hexCode = "0123456789ABCDEF".toCharArray();
private String printHexBinary(byte[] data) {
if (data==null) return null;
StringBuilder r = new StringBuilder(data.length * 2);
for (byte b : data) {
r.append(hexCode[(b >> 4) & 0xF]);
r.append(hexCode[(b & 0xF)]);
}
return r.toString();
}
//**************************************************************************
//** create
//**************************************************************************
/** Creates a new file if one does not exist.
*/
public void create(){
if (exists()) return;
try {
java.io.File file = getFile();
file.getParentFile().mkdirs();
file.createNewFile();
}
catch (Exception e){}
}
//**************************************************************************
//** write
//**************************************************************************
/** Creates a new file using the given ByteArrayOutputStream. Note that this
* method will convert the ByteArrayOutputStream to a byte array using the
* toByteArray() method which may result in memory issues.
*/
public void write(ByteArrayOutputStream bas){
write(bas.toByteArray());
}
//**************************************************************************
//** write
//**************************************************************************
/** Creates a new file using the given byte array.
*/
public void write(byte[] bytes){
java.io.File File = getFile();
attr = null;
if (File!=null){
FileOutputStream output = null;
try {
File.getParentFile().mkdirs();
output = new FileOutputStream(File);
output.write(bytes);
}
catch (Exception e){}
finally {
try { if (output != null) output.close(); }
catch (Exception e){}
}
}
}
//**************************************************************************
//** write
//**************************************************************************
/** Creates a new file using the given InputStream. Note that the caller is
* responsible for closing the input stream after the method is complete.
*/
public void write(InputStream input){
java.io.File File = getFile();
attr = null;
if (File!=null){
FileOutputStream output = null;
try {
File.getParentFile().mkdirs();
output = new FileOutputStream(File);
byte[] buf = new byte[bufferSize];
int i = 0;
while((i=input.read(buf))!=-1) {
output.write(buf, 0, i);
}
}
catch (Exception e){}
finally {
try { if (output != null) output.close(); }
catch (Exception e){}
}
}
}
//**************************************************************************
//** Write Text
//**************************************************************************
/** Used to write text to a file. Uses UTF-8 character encoding. Use the
* other write method to specify a different character encoding (e.g.
* ISO-8859-1).
*/
public void write(String Text){
write(Text, "UTF-8");
}
//**************************************************************************
//** Write Text
//**************************************************************************
/** Used to write text to a file. Allows users to specify character encoding.
*
* @param charsetName Name of the character encoding used to read the file.
* Examples include UTF-8 and ISO-8859-1. If null, the writer will use the
* default character encoding defined on the host machine.
*/
public void write(String Text, String charsetName){
java.io.File File = getFile();
attr = null;
if (File!=null){
Writer output = null;
try {
File.getParentFile().mkdirs();
if (charsetName==null){
output = new BufferedWriter( new FileWriter(File) );
}
else{
output = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(File), charsetName));
}
output.write( Text );
}
catch (Exception e){}
finally {
try { if (output != null) output.close(); }
catch (Exception e){}
}
}
}
//**************************************************************************
//** Write XML
//**************************************************************************
/** Used to write an XML DOM Document to a file.
*/
public void write(org.w3c.dom.Document xml){
write(javaxt.xml.DOM.getText(xml), xml.getXmlEncoding());
}
//**************************************************************************
//** write
//**************************************************************************
/** Used to write a JSON object to a file. Note that the JSON object is
* encoded using UTF-8.
*/
public void write(javaxt.json.JSONObject json){
write(json.toString().getBytes(java.nio.charset.StandardCharsets.UTF_8));
}
//**************************************************************************
//** write
//**************************************************************************
/** Used to write a JSON array to a file. Note that the JSON array is
* encoded using UTF-8.
*/
public void write(javaxt.json.JSONArray arr){
write(arr.toString().getBytes(java.nio.charset.StandardCharsets.UTF_8));
}
//**************************************************************************
//** Write Text
//**************************************************************************
/** Used to write text to a file using an array of strings. A new line is
* created for each entry in the array.
*/
public void write(String[] Content){
java.io.File File = getFile();
attr = null;
if (File!=null){
Writer output = null;
try {
File.getParentFile().mkdirs();
output = new BufferedWriter( new FileWriter(File) );
for (int i=0; i
typedef struct _WIN32_FILE_ATTRIBUTE_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
} WIN32_FILE_ATTRIBUTE_DATA;
*
******************************************************************************/
public static class FileAttributes {
private java.util.Date ftCreationTime;
private java.util.Date ftLastAccessTime;
private java.util.Date ftLastWriteTime;
private long size;
private java.util.HashSet