package org.ba.karlsruhe.filehandler;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.FileReader;
import java.io.BufferedReader;
import java.util.ArrayList;
/**
* A wrapper class which deals with reading and writing of files
*
*/
public class FileHandler {
private File m_file;
private boolean m_writeThrough = true;
private boolean m_hasRead = false;
private ArrayList<String> m_cache = new ArrayList<String>();
/**
* Constructs a new file handler.
* If the given file does not exist, the handler tries to create it.
*
* @param file the file name
*/
FileHandler(File file) throws FileHandlerException {
try {
// create the file if it does not exist
if(!file.exists())
file.createNewFile();
// check if the file permissions are properly set
if(!file.canRead() || !file.canWrite())
throw new FileHandlerException("File does not have right read or write permissions.");
} catch(IOException e) {
throw new FileHandlerException(e);
}
m_file = file;
}
/**
* Constructs a new file handler.
* If the given file name does not exist, the handler tries to create it.
*
* @param fileName the file name
*/
FileHandler(String fileName) throws FileHandlerException {
this(new File(fileName));
}
/**
* If the handler operates in write-through mode, every change to a file
* is immediately written to the file (write-through is default)
*
* If the handler is in write-behind mode (=not write-through), you must
* call write() manually to synchronize the changes
*
* @param writeThrough true, if write-through should be enabled
*/
public void setWriteThrough(boolean writeThrough) {
m_writeThrough = writeThrough;
}
public boolean writeThrough() {
return m_writeThrough;
}
/**
* Call this method to update the file handler cache.
*
* Since we cannot use a notifier like INotify we cannot know when our
* file is dirty. So you need to call this method every time you want an
* updated cache.
*
* @throws FileHandlerException
*/
public void read() throws FileHandlerException {
try {
BufferedReader reader = new BufferedReader(new FileReader(m_file));
// clear cache
m_cache.clear();
// read from file line by line
String currentLine = new String();
while((currentLine = reader.readLine()) != null)
m_cache.add(currentLine);
reader.close();
// mark the file to be read at least once
m_hasRead = true;
} catch(FileNotFoundException e) {
throw new FileHandlerException("Could not find file when trying to read. This should never happen.");
} catch(IOException e) {
throw new FileHandlerException(e.getCause());
}
}
/**
* Returns the file's content as an array of strings.
*
* @return the file content
* @throws FileHandlerException
*/
public String[] getContent() throws FileHandlerException {
// if the file has not been read explicitly, try to read it
if(!m_hasRead)
read();
return m_cache.toArray(new String[0]);
}
/**
* Returns the number of lines the file has
*
* @return the number of lines
* @throws FileHandlerException
*/
public int getLineCount() throws FileHandlerException {
// if the file has not been read explicitly, try to read it
if(!m_hasRead)
read();
return m_cache.size();
}
/**
* Returns the file content at the given line or an empty string if the line
* number is invalid.
* The first line has line number 0.
*
* @param lineNumber the line number
* @return the line at given line number
* @throws FileHandlerException
*/
public String getContentAtLine(int lineNumber) throws FileHandlerException {
// if the file has not been read explicitly, try to read it
if(!m_hasRead)
read();
if(validLineNumber(lineNumber))
return m_cache.get(lineNumber);
else
return "";
}
/**
* Sets the line content to a given string at a given line number
*
* @param lineNumber the line number
* @param line the content
* @throws FileHandlerException
*/
public void setLine(int lineNumber, String line) throws FileHandlerException {
if(validLineNumber(lineNumber)) {
m_cache.set(lineNumber, line);
tryToWrite();
}
}
/**
* Appends a line to the file
*
* @param line the content
* @throws FileHandlerException
*/
public void appendLine(String line) throws FileHandlerException {
m_cache.add(line);
tryToWrite();
}
/**
* Removes the given line from the file
*
* @param lineNumber
* @throws FileHandlerException
*/
public void removeLine(int lineNumber) throws FileHandlerException {
if(validLineNumber(lineNumber))
m_cache.remove(lineNumber);
tryToWrite();
}
/**
* Removes all lines from the file
* @throws FileHandlerException
*/
public void removeAllLines() throws FileHandlerException {
m_cache.clear();
tryToWrite();
}
/**
* Removes all the lines which contain the given pattern
*
* @param match the matching string
* @param caseSensitive if true, the match will be treated case-sensitive
* @return the amount of strings removed
* @throws FileHandlerException
*/
public int removeLines(String match, boolean caseSensitive) throws FileHandlerException {
if(!caseSensitive)
match = match.toLowerCase();
int matchCount = 0;
for(int i=0;i<m_cache.size();i++) {
String compareString;
if(!caseSensitive)
compareString = match.toLowerCase();
else
compareString = match;
if(m_cache.get(i).contains(compareString)) {
matchCount++;
m_cache.remove(i);
}
}
tryToWrite();
return matchCount;
}
public void write() throws FileHandlerException {
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(m_file,false));
for(int i=0;i<m_cache.size();i++) {
writer.write(m_cache.get(i));
if(i!=m_cache.size()-1)
writer.newLine();
}
writer.close();
} catch(FileNotFoundException e) {
throw new FileHandlerException("Could not find file when trying to read. This should never happen.");
} catch(IOException e) {
throw new FileHandlerException(e.getCause());
}
}
private void tryToWrite() throws FileHandlerException {
if(m_writeThrough)
write();
}
private boolean validLineNumber(int lineNumber) {
return lineNumber >= 0 && lineNumber < m_cache.size();
}
}