I have this current implementation but I couldn't append the new data that were being passed on in processName, activity and numberOfRecords. It just keeps creating a separate .txt file for each transaction.
#Override
public void saveSummaryLogs(String processName, String activity,
int numberOfRecords) throws Exception {
log.info("Test if this method is being executed.");
log.info(INSERT_LOGS_TO_FILE);
log.info("Creating a folder directory is being executed!");
try {
File f = new File(summaryLogsDbDir);
f.mkdirs();
} catch (Exception e) {
throw new Exception("Permission denied to create parent folder.",
e);
}
writeToFile(processName, activity, numberOfRecords);
log.info("writeToFile has been called and executed!");
}
public void writeToFile(String processName, String activity,
int numberOfRecords) throws Exception {
log.info("writeToFile is being executed!");
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("ddMMyyy_HHmmss");
try (BufferedWriter out = new BufferedWriter(new FileWriter(
summaryLogsDbDir + LOGS_FILENAME + dateFormat.format(date)
+ ".txt"))) {
out.append(dateFormat.format(date)+ ": " + processName + "\n");
out.append(dateFormat.format(date)+ ": " + activity + "\n");
out.append(dateFormat.format(date)+ ": " + numberOfRecords + "\n");
} catch (Exception e) {
throw new Exception("Failed a summary-logs.txt file.", e);
}
log.info("writeToFile has been executed!");
}
Any help of advise is greatly appreciated. Thanks!
Related
I tried to scan a text file and rewrite it with one change. However, the scanner does not have a new line, although there is already something in the text file. What could be the reason?
public class ThemeStatus {
public void statusChanger(String subject, String name) {
PrintWriter fileWriter = null;
File themeFile = new File("FüFolder/Themenübersicht/" + subject + "/Settings.txt");
Scanner fileScanner = null;
try {
fileWriter = new PrintWriter(themeFile);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
try {
fileScanner = new Scanner(themeFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println(fileScanner.hasNextLine());
if(fileScanner.hasNextLine()) {
while(fileScanner.hasNextLine()) {
String line = fileScanner.nextLine();
if(line.contains("CurrentTheme")) {
fileWriter.println("CurrentTheme = " + name);
}
else {
fileWriter.println(line);
}
}
}
else {
fileWriter.println("CurrentTheme = " + name);
}
fileWriter.close();
}
I am trying to edit a json file by 5 different threads and then copy it 5 times, as well, to the same destination path. As you see, there are concurrency problems.
I tried this for the copy method:
public static void copyFile(String originPath, String destinationPath, String file) throws IOException {
logger.debug("Starting copyFile of" + file);
FileChannel channel = null;
File lockFile = new File(originPath + file);
try {
logger.debug("Comienza el proceso de procesado del json del fichero:" + file);
channel = extracted(lockFile).getChannel();
FileLock fileLock = null;
try {
fileLock = channel.lock();
} catch(OverlappingFileLockException e) {
logger.error("3 "+e.getMessage());
Thread.sleep(200);
}
FileUtils.copyFile(FileUtils.getFile(originPath + file), FileUtils.getFile(destinationPath + file));
logger.debug("The copy of " + file + " ends.");
fileLock.release();
channel.close();
} catch (IOException e) {
logger.error("Failing to copy "+file " to " + destinationPath + e.getMessage());
}
}
I'm getting nulls and IOExceptions.
All I want is that when a file is processed the other threads just wait for it in a queue, one after each other.
If I understand correctly your problem is when one of your threads tries to copy one file, other threads wait in a queue and then start their work one by one.
you can achieve this by code below
public class FileLock {
static Semaphore semaphore = new Semaphore(1);
public static void copyFile(String originPath, String destinationPath, String file) throws IOException {
try {
semaphore.acquire();
logger.debug("Comienza el proceso de procesado del json del fichero:" + file);
FileUtils.copyFile(FileUtils.getFile(originPath + file), FileUtils.getFile(destinationPath + file));
logger.debug("The copy of " + file + " ends.");
} catch (IOException | InterruptedException e) {
logger.error("Failing to copy " + file" to " + destinationPath + e.getMessage());
} finally {
semaphore.release();
}
}
}
So lately i ve been trying to wrap my head around concurrency. And currently I m trying to find a solution for the ReaderWriter Problem.
I got a class File, it counts the number of Readers/Writers and has two Semaphores.
When a Reader tries to read it has to wait as long as there is a Writer Thread writing. When it enters readCount gets incremented within the readerSemaphore
& decremented within the same Semaphore when it leaves.
When a Writer tries to enter it has to wait for as long as there is more than one reader. When it enters it aquires the writerSemaphore and increaese the writerCount. When it leaves it releases the Semaphore.
For some reason that I cant figure out the Writers are not editing the String file in class File.
Thanks in advance :)
public class Main {
public static void main(String[]args) {
File file = new File("1. Chapter: ");
Writer w1 = new Writer(file, " w1 ");
Writer w2 = new Writer(file, " w2 ");
Reader r1 = new Reader(file);
Reader r2 = new Reader(file);
Reader r3 = new Reader(file);
Reader r4 = new Reader(file);
Reader r5 = new Reader(file);
w1.start();
w2.start();
r1.start();
r2.start();
r3.start();
r4.start();
r5.start();
try {
w2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-> Final output: " + file.file);
}}
public class File {
public String file;
private int readCount;
private int writeCount;
private Semaphore semReader;
private Semaphore semWriter;
public File(String file) {
this.file = file;
readCount = 0;
writeCount = 0;
semReader = new Semaphore(1);
semWriter = new Semaphore(1);
}
public synchronized void startReading() {
try {
while(writeCount == 1) {
Thread.currentThread().wait();
}
semReader.acquire();
readCount++;
semReader.release();
System.out.println(" --- File was read");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized String endReading() {
String temp = file;
try {
semReader.acquire();
readCount--;
semReader.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
return temp;
}
public synchronized void startWriting(String edit) {
try {
while(readCount > 0) {
Thread.currentThread().wait();
}
semWriter.acquire();
writeCount++;
System.out.println(" --- File got edited");
file = file + "hi";
}
catch (Exception e) {
}
}
public synchronized void endWriting() {
writeCount--;
semWriter.release();
}}
public class Writer extends Thread {
private File file;
private String edit;
public Writer(File file, String edit) {
this.file = file;
this.edit = edit;
}
#Override
public void run() {
Random rand = new Random();
try {
sleep(1000);
System.out.println(">W: " + Thread.currentThread().getName() + " started first write.");
file.startWriting(" first" + edit);
sleep(3000);
System.out.println(">W: " + Thread.currentThread().getName() + " ended first write.");
file.endWriting();
sleep(2000);
System.out.println(">W: " + Thread.currentThread().getName() + " started second write.");
file.startWriting(" second" + edit);
sleep(3000);
System.out.println(">W: " + Thread.currentThread().getName() + " ended second write.");
file.endWriting();
System.out.println(">W: " + Thread.currentThread().getName() + " finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
}}
public class Reader extends Thread {
private File file;
public Reader(File file) {
this.file = file;
}
#Override
public void run() {
Random rand = new Random();
try {
sleep(rand.nextInt(2000));
System.out.println(">R: " + Thread.currentThread().getName() + " startet first read.");
file.startReading();
sleep(3000);
System.out.print(">R: " + Thread.currentThread().getName() + " ended first read: ");
System.out.println(file.endReading());
sleep(rand.nextInt(2000));
System.out.println(">R: " + Thread.currentThread().getName() + " startet second read.");
file.startReading();
sleep(3000);
System.out.print(">R: " + Thread.currentThread().getName() + " ended second read: ");
System.out.println(file.endReading());
System.out.println(">R: " + Thread.currentThread().getName() + " finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
}}
Edit:
Thread.currentThread().wait() was wrong.
Waiting on threads is discouraged in the java docs.
Thanks, #JB Nizet for helping me.
I would like to have a full code coverage of my method writeList(), but I don't know how to cover catch blocks.
My method is :
public class ListOfNumbers {
//...another code...
public void writeList() {
try (FileOutputStream inputStream = new FileOutputStream(this.pathOut);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(inputStream);
PrintWriter out = new PrintWriter(outputStreamWriter)) {
for (int i = 0; i < this.numbers.size(); i++) {
out.println("Value at: " + i + " = " + this.numbers.get(i));
}
} catch (final ArrayIndexOutOfBoundsException e) {
ListOfNumbers.LOGGER.error("Caught ArrayIndexOutOfBoundsException: " + e.getMessage(),
e);
} catch (final FileNotFoundException e) {
ListOfNumbers.LOGGER.error("Caught FileNotFoundException: " + e.getMessage(), e);
} catch (final IOException e) {
ListOfNumbers.LOGGER.error("Caught IOException: " + e.getMessage(), e);
}
}
}
To do it, If I were you, I would rewrite my code to make it more testable by moving the code that write the numbers into a different method, in order to mock this new method to make it throw whatever you want using Mockito.
So your code could be something like that:
public void writeList() {
try (FileOutputStream inputStream = new FileOutputStream(this.pathOut);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(inputStream);
PrintWriter out = new PrintWriter(outputStreamWriter)) {
// Delegate the way to write the numbers to this new method
writeNumbers(out);
} catch (final ArrayIndexOutOfBoundsException e) {
ListOfNumbers.LOGGER.error(
"Caught ArrayIndexOutOfBoundsException: " + e.getMessage(), e
);
} catch (final FileNotFoundException e) {
ListOfNumbers.LOGGER.error("Caught FileNotFoundException: " + e.getMessage(), e);
} catch (final IOException e) {
ListOfNumbers.LOGGER.error("Caught IOException: " + e.getMessage(), e);
}
}
/**
* The new method that is protected here but could also be package protected
* but cannot be private to be able to override it.
*/
protected void writeNumbers(PrintWriter out) {
for (int i = 0; i < this.numbers.size(); i++) {
out.println("Value at: " + i + " = " + this.numbers.get(i));
}
}
Then your unit test could be:
#Test
public void causeAIOException() {
ListOfNumbers lon = // Create your instance here
// Create a Spy to be able to mock the method writeNumbers
ListOfNumbers listOfNumbers = Mockito.spy(lon);
// This will make any call to writeNumbers throw a IOException
Mockito.doThrow(IOException.class).when(listOfNumbers)
.writeNumbers(Matchers.any(PrintWriter.class));
// Call the method on the spy
listOfNumbers.writeList();
}
NB: In case of FileNotFoundException, you could simply provide an existing folder as pathOut as it is one of the cases for which new FileOutputStream will throw a FileNotFoundException and it is easy to reproduce.
class ListOfNumbers {
public void writeList() throws ArrayIndexOutOfBoundsException,FileNotFoundException,IOException {
try (FileOutputStream inputStream = new FileOutputStream(this.pathOut);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(inputStream);
PrintWriter out = new PrintWriter(outputStreamWriter)) {
for (int i = 0; i < this.numbers.size(); i++) {
out.println("Value at: " + i + " = " + this.numbers.get(i));
}
}
}
public class Main{
public static void main(String [] args){
try{
ListOfNumbers list=new ListOfNumbers();
try{
list.writeList();
}
} catch (ArrayIndexOutOfBoundsException e) {
ListOfNumbers.LOGGER.error("Caught ArrayIndexOutOfBoundsException: " + e.getMessage(),
e);
} catch (FileNotFoundException e) {
ListOfNumbers.LOGGER.error("Caught FileNotFoundException: " + e.getMessage(), e);
} catch (IOException e) {
ListOfNumbers.LOGGER.error("Caught IOException: " + e.getMessage(), e);
}
}
}
}
I Couldn't write continuously to the file. I want to have a function that has to append to the file. But, I couldn't get what I need. Can anybody help me if there is any mistake with the code written.
void writeLog(String s)
{
try
{
String filename= "D:\\Gardening\\Logs.txt";
FileWriter fw = new FileWriter(filename,true); //the true will append the new data
fw.write(s+"\n");//appends the string to the file
fw.close();
}
catch(IOException ioe)
{
System.err.println("IOException: " + ioe.getMessage());
}
}
Guys, I found the problem in the constructor of the class, The full code is here
Class Log
{
Log()
{
try{
FileWriter fw=new FileWriter("path of file");
}
catch(Exception a)
{
System.err.println(a);
}
}
void writeLog(String s)
{
try
{
String filename= "D:\\Gardening\\Logs.txt";
FileWriter fw = new FileWriter(filename,true); //the true will append the new data
fw.write(s+"\n");//appends the string to the file
fw.close();
}
catch(IOException ioe)
{
System.err.println("IOException: " + ioe.getMessage());
}
}
As it was being called in the constructor again and again It was happening like that.
Just tested your code and it's working fine. Can you post your full code ? Also how are you calling the writeLog method.
public class Test {
void writeLog(String s) {
try {
String filename = "C:\\Temp\\Logs.txt";
FileWriter fw = new FileWriter(filename, true);
fw.write(s + "\n");
fw.close();
} catch (IOException ioe) {
System.err.println("IOException: " + ioe.getMessage());
}
}
public static void main(String[] args) {
Test t1 = new Test();
for (int i = 0; i < 5; i++) {
t1.writeLog("Hello");
}
}
}
This code creates a Logs.txt with the following content -
Hello
Hello
Hello
Hello
Hello
Try to create your FileWriter outside of the method where you call it and give it to your method as a second parameter.(If you will append strings to your file in whole project, you can create your FileWriter as singleton) There is no need to recreate FileWriter again and again.
By the way you should close FileWriter in finally block. Because in your code if an exception occured before close operation FileWriter cannot be closed. My code advice is like below:
public static void main(String[] args) {
FileWriter fw = null;
try {
fw = new FileWriter(filename,true);
writeLog("Your String", fw);
} catch (IOException ioe) {
System.err.println("IOException: " + ioe.getMessage());
}
finally
{
try {
if(fw != null)
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
static void writeLog(String s , FileWriter fw)
{
try
{
fw.write(s+"\n");
}
catch(IOException ioe)
{
System.err.println("IOException: " + ioe.getMessage());
}
}