Closing a file after writing recursively - java

I don't know why my code only writes in the file the first time and then nothing, I think the problem is salida.close() but i'm not sure. A bit of help will be appreciated. The method itself saves a binary tree in a file. If you need more information, ask me. Here is my code:
public boolean guardarAgenda() throws IOException
{
NodoAgenda raiz;
raiz = this.root;
guardar(raiz);
if(this.numNodes == 0)
return true;
else return false;
}
public void guardar(NodoAgenda nodo) throws IOException
{
FileWriter fich_s = new FileWriter("archivo.txt");
BufferedWriter be = new BufferedWriter(fich_s);
PrintWriter output = new PrintWriter(be);
Parser p = new Parser();
if (nodo != null)
{
guardar(nodo.left);
p.ponerPersona(nodo.info);
String linea = p.obtainLine();
salida.println(linea);
guardar(nodo.right);
this.numNodes--;
}
output.close();
}

You are opening the same file on multiple calls without even the option of appending content. So no wonder you are not finding what you expect in it once processing ended.
When working with recursion and using the same resource on each call it's better to have a second method that takes that result as argument, and does only the writing/adding to it, opening/instantiation should happen in a method which initiates the first call, something similar to this:
public void guardar(NodoAgenda nodo) throws IOException
{
FileWriter fich_s = new FileWriter("archivo.txt");
BufferedWriter be = new BufferedWriter(fich_s);
PrintWriter salida = new PrintWriter(be);
if (nodo != null)
{
guardar(nodo.left, salida);
}
output.close();
}
public void guardar(NodoAgenda nodo, PrintWriter salida) throws IOException
{
if (nodo != null)
{
Parser p = new Parser();
guardar(nodo.left);
p.ponerPersona(nodo.info);
String linea = p.obtainLine();
salida.println(linea);
guardar(nodo.right, salida);
this.numNodes--;
}
}

Related

How to use Mockito/PowerMockito to trigger IOException for Unit/Integration Testing

I am doing testing on the following piece of code, and i am having trouble getting this method to throw an IOException so i can get 100% coverage.
I have tried to mock the CharArrayReader, StringWriter classes but to no avail.
Would appreciate any help!
Class to test
public static final String getValue(String content) {
if (content == null) return null;
CharArrayReader reader = new CharArrayReader(content.toCharArray());
StringWriter writer = new StringWriter();
try {
int c;
while ((c = reader.read()) != -1) {
if (isChinese((char)c)) {
writer.write(c);
} else {
if ( (char)c > 0x20 && (char)c < 0x7f ) {
writer.write(c);
} else {
writer.write(' ');
}
}
}
} catch (IOException e) {
return null;
} finally {
reader.close();
}
return writer.toString();
}
My Attempts
#Test
public void getValue_Exception() throws IOException {
String content = "asd";
char[] chara = null;
CharArrayReader reader = mock(CharArrayReader.class);
when(content.toCharArray()).thenReturn(chara);
when(reader.read()).thenThrow(IOException.class);
StringWriter writer = mock(StringWriter.class);
doThrow(IOException.class).when(writer).write(anyInt());
spyController.getValue(content);
}
While reading inside the CharArrayReader class, the IOException is thrown when the char[] buff parameter in the constructor is null.
private void ensureOpen() throws IOException {
if (buf == null)
throw new IOException("Stream closed");
}
One approach (even if it is a bad idea to mock the String class) is to mock the call of the method toCharArray() from the String class to return a null value.
The only scenario, in which CharArrayReader::read throws IOException is when the stream is closed. In your example it seems rather impossible.
Nevertheless, if you really want to get that 100% coverage or just make sure your class behaves in case of unexpected, my advise would be to create a factory for your reader e.g.:
class ReaderFactory {
Reader create(String content) {
return new CharArrayReader(content.toCharArray());
}
}
With this class in place, you could use it in your code and mock the create method. This way you would have control over the instance of Reader being used in your test case.

Pass in file text into hashmap

I am having a bit of an issues trying to pass in a file read by my program and sorted accordantly. I am not used to working with files, and i ran out of ideas as to how this could be achieved.
/////////////////////////////////////// class reads file ///////////////////////////////////
import java.io.*;
public class InFileReader {
private BufferedReader inputStream = null;
private String fileLine;
private StringBuilder sb;
public String getFile(File fileRead) throws FileNotFoundException,
IOException {
inputStream = new BufferedReader(new FileReader(fileRead)); //reads files
sb = new StringBuilder();
while((fileLine = inputStream.readLine()) != null){//keep reading lines in file till there is none
sb.append(fileLine).append("\n");
}
return sb.toString(); //returns StringBuffer read values in String form
}
}
///////////////////////////////////////////////////// end of read file class ///////////////////////
public void getFile(File fileRead) throws FileNotFoundException,
IOException {
try {
String input = fileReader.getFile(fileRead.getAbsoluteFile());
HashMap<Integer, Thing.Ship> hashmap = new HashMap<>();
while (!input.isEmpty()) { // as long as there is data in the file keep looping
Scanner sc = new Scanner(input); // scan file
if (!input.startsWith("//")) { // take out "//" from directory
String type = "";
if (sc.hasNext()) { // if there are character lines get next line
type = sc.next();
}
if (type.equalsIgnoreCase("port")) { // looks for "port"
world.assignPort(new Thing.SeaPort(sc)); // assigns value to Seaport
} else if (type.equalsIgnoreCase("dock")) {
world.assignDock(new Thing.Dock(sc));
} else if (type.equalsIgnoreCase("ship")) {
Thing.Ship s = new Thing.Ship(sc);
hashmap.put(s.getIndex(), s);
world.assignShip(s);
} else if (type.equalsIgnoreCase("pship")) {
Thing.Ship s = new Thing.PassengerShip(sc);
hashmap.put(s.getIndex(), s);
world.assignShip(s);
} else if (type.equalsIgnoreCase("cship")) {
Thing.Ship s = new Thing.CargoShip(sc);
hashmap.put(s.getIndex(), s);
world.assignShip(s);
} else if (type.equalsIgnoreCase("person")) {
world.assignPerson(new Thing.Person(sc));
}
}
}
//inputOut.setText(type);
inputOut.setText(world.toString());
} catch (Exception e) {
System.out.println(e + "-----");
}
}
Here fileRead knows where to find the file to be read "C:\Users\abe\IdeaProjects\CreateSeaPortDataFile\src\text.txt"
public void getFile(File fileRead) throws FileNotFoundException,
IOException {
this is where things just fall apart:
String input = fileReader.getFile(fileRead.getAbsoluteFile());
My intent here is to pass the location of the file so that the getFile class can read it and then be sorted into the hashmap.
again i am not familiar with how to work with file, any suggestion or comment would be greatly appreciated.
thank you in advanced.
If you get a FileNotFoundException then the file was not found.
You say the filename was "C:\Users\abe\IdeaProjects\CreateSeaPortDataFile\src\text.txt".
If you type that name in the code you must escape the backslash:
"C:\\Users\\abe\\IdeaProjects\\CreateSeaPortDataFile\\src\\text.txt".

Comparing ArrayList with user input

I have been trying to compare the file content with user input. The program is reading from a specific file and it checks against the user's string input. I am having trouble comparing the ArrayList with the user input.
public class btnLoginListener implements Listener
{
#Override
public void handleEvent(Event arg0)
{
//variables for the class
username = txtUsername.getText();
password = txtPassword.getText();
MessageBox messageBox = new MessageBox(shell, SWT.OK);
try {
writeFile();
messageBox.setMessage("Success Writing the File!");
} catch (IOException x)
{
messageBox.setMessage("Something bad happened when writing the file!");
}
try {
readFile("in.txt");
} catch (IOException x)
{
messageBox.setMessage("Something bad happened when reading the file!" + x);
}
if (username.equals(names))
{
messageBox.setMessage("Correct");
}
else
{
messageBox.setMessage("Wrong");
}
messageBox.open();
}
}
private static void readFile(String fileName) throws IOException
{
//use . to get current directory
File dir = new File(".");
File fin = new File(dir.getCanonicalPath() + File.separator + fileName);
// Construct BufferedReader from FileReader
BufferedReader br = new BufferedReader(new FileReader(fin));
String line = null;
while ((line = br.readLine()) != null)
{
Collections.addAll(names, line);
}
br.close();
}
I am assuming you are trying to check whether an element exists in the list. If yes, then you need to use contains method, here's the Javadoc.
So, instead of using if (username.equals(names)), you can use if (names.contains(username)).
Apart from this, you should make the following changes:
Don't read the file every time an event is called. As you are reading a static file, you can read it once and store it in an ArrayList.
Make variables username and password local.
Remove writeFile() call unless it's appending/writing dynamic values on each event.

Cache file in memory and read in parallel

I've a program (simple log parser) that's so slow couse in some cases it had to full scan input file. So I think to pre-cache the entire file (~100MB) in and read it with multiple thread.
With actual configuration I use the BufferedReader to do the "main read" and RandomAccessFile to goto onto specific offset and read what I need.
I've tried this way:
..
Reader reader = null;
if (cache) {
// caching file in memory
br = new BufferedReader(new FileReader(file));
buffer = new StringBuilder();
for (String line = br.readLine(); line != null; line = br.readLine()) {
buffer.append(line).append(CR);
}
br.close();
reader = new StringReader(buffer.toString());
} else {
reader = new FileReader(file);
}
br = new BufferedReader(reader);
for (String line = br.readLine(); line != null; line = br.readLine()) {
offset += line.length() + 1; // Il +1 รจ per il line.separator
matcher = Constants.PT_BEGIN_COMPOSITION.matcher(line);
if (matcher.matches()) {
linecount++;
record = new Record();
record.setCompositionCode(matcher.group(1));
matcher = Constants.PT_PREFIX.matcher(line);
if (matcher.matches()) {
record.setBeginComposition(Constants.SDF_DATE.parse(matcher.group(1)));
record.setProcessId(matcher.group(2));
if (cache) {
executor.submit(new PubblicationParser(buffer, offset, record));
} else {
executor.submit(new PubblicationParser(file, offset, record));
}
records.add(record);
} else {
br.close();
throw new ParseException(line, 0);
}
}
}
In the PubblicationParser there is a init() method that choose what custom reader to use. A RandomAccessFileReader:
if (file != null) {
this.logReader = new RandomAccessFileReader(file, offset);
} else if (sb != null) {
this.logReader = new StringBuilderReader(sb, (int) offset);
}
And this is my 2 custom reader:
//
public class StringBuilderReader implements LogReader {
public static final String CR = System.getProperty("line.separator");
private final StringBuilder sb;
private int offset;
public StringBuilderReader(StringBuilder sb, int offset) {
super();
this.sb = sb;
this.offset = offset;
}
#Override
public String readLine() throws IOException {
if (offset >= sb.length()) {
return null;
}
int indexOf = sb.indexOf(CR, offset);
if (indexOf < 0) {
indexOf = sb.length();
}
String substring = sb.substring(offset, indexOf);
offset = indexOf + CR.length();
return substring;
}
#Override
public void close() throws IOException {
// TODO Auto-generated method stub
}
}
//
public class RandomAccessFileReader implements LogReader {
private static final String FILEMODE_R = "r";
private final RandomAccessFile raf;
public RandomAccessFileReader(File file, long offset) throws IOException {
this.raf = new RandomAccessFile(file, FILEMODE_R);
this.raf.seek(offset);
}
#Override
public void close() throws IOException {
raf.close();
}
#Override
public String readLine() throws IOException {
return raf.readLine();
}
}
The problem is that the "cache way" is so slow and I understand why!
You should be making sure that it is indeed the I/O making your application slow, not something else (e.g inefficient logic in your parser). For that, you could use a Java profiler (JProfiler, for example).
If it is indeed I/O, then it might be better to use some ready-made solution to load the file into memory - essentially that's what you are trying to implement yourself.
Have a look at MappedByteBuffer and ByteBuffer.

FXML and lambda expressions in Java not working?

I'm working on rewriting my simple Contacts app from normal JAVA FX to FXML.THe problem is in Lambda expressions. I have interface like:
interface ObjectCreator {
void create(String[] array);
}
And the problem is when i use this CSVFileReader:
public static class CSVFileReader {
String fileName;
CSVFileReader(String fileName) {
this.fileName = fileName;
}
void read(ObjectCreator creator) {
try {
BufferedReader csv = new BufferedReader(new FileReader(fileName));
String row = csv.readLine();
while (row != null) {
creator.create(row.split(","));
row = csv.readLine();
}
csv.close();
} catch (IOException e) {
}
}
}
In this code i use lambda expression to read Contacts from file:
#FXML
public void openFile() {
FileChooser fileChooser = new FileChooser();
File fileE = fileChooser.showOpenDialog(scene.getWindow());
if (fileE != null) {
CSVFileReader reader = new CSVFileReader(fileE.getName());
data.clear();
reader.read(v ->
data.add(new Contact(v[0], v[1], v[2], v[3])));
}
System.out.println("open list");
}
I use JDK 1.8.65 so preeety new one. Problem is that there is no error or exception just looks like code "v->data.add(new Contact(v[0], v[1], v[2], v[3]))" would not be invoked.
Question is am I doing something wrong or it just wont be working??
Ok no question, after futher studying my app i discovered i was taking
fileE.getName();
and i should take
fileE.getAbsolutePath();
So the app would look in proper location for a file.

Categories

Resources