closing BufferedReader results in Stream closed in Junit - java

I have several JUnit tests, all of them are invoking the same class (with different inputs), and check for the return value of this class.
The class itself has a code that uses BufferedReader, that is being closed at the end of the read.
The first test is passing, but every test after it is throwing the Stream closed
I am creating a new instance of the class in each test, as well as a new BufferReader in the read code.
Aren't tests supposed to be contained? isn't a new instance should resolve this issue?
My Example Tests (omitted code that generates different args in each test for readability)
public void test1() {
float result = 0;
MyClass myClassInst = new MyClass();
result = myClassInst.Execute(args);
assert (result > 0.5);
}
public void test2() {
float result = 0;
MyClass myClassInst = new MyClass();
result = myClassInst.Execute(args);
assert (result > 0.5);
}
Within myClass I have the following code (INPUT_STREAM is a txt file in my project resources and is identical for every test)
ReadInputsClass re = new ReadInputsClass(INPUT_STREAM);
which invokes the following method
___EDIT_________
The way I am getting INPUT_STREAM is:
at the top of MyClass I have
private static InputStream INPUT_STREAM= initializeInputStream();
private static InputStream initializeInputStream() { InputStream inputStream = System.class.getResourceAsStream("textFile.txt"); return inputStream; }
___END EDIT_____
the ReadInputsClass constructor is calling the following code
private ArrayList<SomeClass> readStream(InputStream inputStream) {
ArrayList<SomeClass> ret = new ArrayList<SomeClass>();
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(inputStream));
String line = br.readLine();
while (line != null) {
// do some stuff on the line just read
line = br.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null)
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return ret;
}
Clearly the issue is coming from the br.close in this code
when I put a break point, the 2nd test is getting to br that is set to null, creating a new br, and when it is reaching the br.readLine() it is throwing the stream close.
I do not understand why? Isn't the new br = new BufferedReader should start fresh?

You are nesting streams in your code:
br = new BufferedReader(new InputStreamReader(inputStream));
In Java, if you close the outer most stream, all other streams in the chain are closed as well. That means if you call br.close(), then the close() method on the InputStreamReader gets called which in turn calls the close method on your inputStream variable.
If you initialize INPUT_STREAM as a static variable and re-use it, that would mean subsequent tests using the INPUT_STREAM variable will use a stream that has already been closed.

Related

BufferedReader reads just one line in an multiple line file

I tried to archive that a multiline file will be read from an BufferedReader. But this BufferedReader reads just one line and exiting his while(). Before he can read this, another method of the same class should've been written in this file (not at the same time), mostly more than one line. The file contains different types of variables, such as int[], int, double[], String. At the end of one object, or nearly just the data that I've to collect that I can re-calculate the whole object, the ObjectOutputStream pastes "\n". I just write parsed Strings in this file.
In my case, it's a workaround for the ObjectInputStream, cause this stream throws an EOFException every time. For those who don't know the EOFException: it will be thrown if the reader reaches end of file while reading.
I tried to:
set the input string for the BufferedReader to another line
.close() the Reader and make it new
set while(1)
write other Datatypes, such as the whole Object
but all without any changes. The BufferedReader reads just one line and the ObjectInputStream throws EOFException.
LinkedList<SomeAnotherSelfMadeClass> list;
File file = new File(fullPath) // fullPath = absolute path to the file
FileInputStream fileInputStream;
BufferedReader bufferedReader;
public static LinkedList<SomeAnotherSelfMadeClass> readFile()
{
list = new LinkedList<SomeAnotherSelfMadeClass>();
fileInputStream = new FileInputStream(file); // could be FileReader
bufferedReader = new BufferedReader(fileInputStream);
String helper, anotherHelper;
while ((helper = bufferedReader.readLine()) != null)
{
while ((anotherHelper = scanner.hasNext()) != null)
// here's some code with scanner-things, it shouldn't be necessary to
// know. In fact the scanner help to gather the data from the file and
// create an object of SomeAnotherSelfMadeCLass and put it into the list
}
bufferedReader.close();
fileInputStream.close();
return list;
}
What can I do that I can read all lines of the file and re-calcuate my objects that are pasted in there?
I don't know either; it is better to work with the ObjectInputStream or with the BufferedReader? What can I do that the ObjectInputStream don't throws the EOFException (every time I worked with the ObjectInputStream I wrote the whole Object via ObjectOutputStream)?
P.S.: I don't have internet atm at home, so it could take a while that I'm able to answer.
Try with this structure of code..
BufferedReader objReader = null;
public static LinkedList<SomeAnotherSelfMadeClass> readFile()
{
list = new LinkedList<SomeAnotherSelfMadeClass>();
try {
objReader = new BufferedReader(new FileReader(fullPath));
while ((helper= objReader.readLine()) != null) {
...........
System.out.println(helper);//just for checking
while ((anotherHelper = scanner.hasNextLine()) != null){
.....
....
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (objReader != null)
objReader.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
I'm a little idiot, you have to know.
The second while() had the condition (anotherHelper = scanner.next()) != null, not that what I stated before.
But I managed to get another outputs, even I tried this before (it seems that I'd misstyped at any point);
I set the first while() to true, test helper to break out of the while() and deleted the second while:
while(true)
{
helper = bufferedReader.readLine();
if (helper.equals(null))
break;
// making things with the scanner
}
It seems that the compiler had a problem with this double-while. And optimized it wrong; I think he made
while (((helper = bufferedReader.readLine() != null) && (helper = scanner.nextLine()) != null)
out of this peace of code. That would explain why it only run once and returns true if I test it with System.out.println(scanner.hasNext(); and System.out.println(scanner.hasNextLine(); BEFORE the second while, but in it he returns not even false.

Reading a text file after updating it iteratively without stopping the program

I am reading a text file in my program and do some modifications in the file and then without stopping the program, I iteretively read the file and again and again, and each time I should be able to read the most recent version of the file. however, after first modification in the file, other times I am still getting that version of the file and seems other modifications are not applied.
Here is how I read the file:
public static Map<String, Float> readOwnersBiasFile() throws IOException {
FileInputStream file = new FileInputStream("ownersBias.txt");
Map<String, Float> ownerBiasMap = new HashMap<String, Float>();
//Construct BufferedReader from InputStreamReader
BufferedReader br = new BufferedReader(new InputStreamReader(file));
String line = null;
while ((line = br.readLine()) != null) {
String[] var = line.split("\\^");
ownerBiasMap.put(var[0], Float.valueOf(var[1]));
}
br.close();
return ownerBiasMap;
}
and here is how I store my modifications:
public static void storeOwnersUtilityMap(Map<String, Float> ownersUtilityMap) throws IOException {
FileInputStream fileInputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
List<String> lines = new ArrayList<String>();
try {
fileInputStream = new FileInputStream("ownersBias.txt");
inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
bufferedReader = new BufferedReader(inputStreamReader);
String s;
String[] var;
if (bufferedReader.readLine() == null) {
for (Map.Entry<String, Float> entry : ownersUtilityMap.entrySet()) {
lines.add(entry.getKey().concat("^").concat(String.valueOf(entry.getValue())));
}
} else
while ((s = bufferedReader.readLine()) != null) {
var = s.split("\\^");
if (ownersUtilityMap.containsKey(var[0]))
s = var[0].concat("^").concat(String.valueOf(ownersUtilityMap.get(var[0])));
lines.add(s);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(bufferedReader);
IOUtils.closeQuietly(inputStreamReader);
IOUtils.closeQuietly(fileInputStream);
}
fileWriter(lines, "ownersBias.txt");
}
private static void fileWriter(List<String> list, String fileName) throws IOException {
File fout = new File(fileName);
FileOutputStream fos = new FileOutputStream(fout);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
bw.write(iterator.next());
bw.newLine();
}
bw.close();
}
And in my main method I have a loop that do some stuff along with reading and modification of the text file.
public static void main(String[] args) throws IOException, TasteException {
for(int i=0;i<10;i++){
map= readOwnersBiasFile();
do some stuff;
storeOwnersUtilityMap(map);
}
}
Should not be necessary to close the programs between re-reads, I've written programs that would read the same file and get any external changes. So that part I know works.
Now the top method readOwnersBiasFile() does not seem to close everything explicitly; I see the BufferedReader closed, but not the InputStreamReader or FileInputStream. When leaving the method, the objects have no references and therefore garbage collection should find them, timing could be an issue. I recommend try-with-resources for anything Closeable.
Operating system might cause differences, however, especially if you're both writing and reading from the same JVM. For example, in Windows you can't delete/move/rename an already open file, but *nix you can. What I don't know (partially because I don't know you're runtime platform) is whether the JVM is being tricky with file handles and tries to reuse in such a way that the changes aren't flushed from the write before things are read or whatever.
If might be worthwhile examining properties on your File object, make sure you see size changes or changed last modified dates or whatever that might indicate you're actually picking up the differences.
I also can't tell anything about the order you're calling things (in particular the first two blocks of code), whether you're doing things multithreaded or what. Open/reading/writing in a multithreaded environment might be problematic

File IO with android.os.memoryfile

I am trying to write to a file using android.os.memoryfile and then read from the same file. I write to the file in one method and read from another method, all in the same class. I can write fine but When I read the file I get lines of a symbol instead of the content I had written to the file. It seems that the read method is not reading the file I had written to.
If I put code to write and read the file in same method, it seems to work fine. Reading file outputs the string I had written.
Here is my code:
public class FileActivity extends Activity {
MemoryFile memFile;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
memFile = new MemoryFile("MemoryFileTest", 1000000);
} catch (IOException e) {
e.printStackTrace();
}
}
public void readFile () {
StringBuffer strBuffer = new StringBuffer();
try {
InputStream in = memFile.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String inputString;
while ((inputString = reader.readLine()) != null) {
strBuffer.append(inputString + "\n");
}
in.close();
reader.close();
Log.d(TAG, strBuffer.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
public void writeFile () {
String example = "This is an example";
byte[] bytes = example.getBytes();
try {
OutputStream out = memFile.getOutputStream();
out.write(bytes);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
In the above code, the MemoryFile is declared in top of class, and initialized in onCreate() method. I am then trying to write and read with that one MemoryFile.
What am I missing here?
I've not used MemoryFile and only starting learning about it for this question. I looked at the source code from within Android Studio. I couldn't find the raw source on the Web. The grepcode version is here. From my experiments and looking at the source code, it's clear that the end-of-file concepts we expect from file-based streams don't apply to a MemoryFile. The end-of-file is based on the length specified in the MemoryFile constructor, not the number of bytes that have been written to the file. Given this, the behavior of BufferedReader.readline(), which you are using in your code, is not well defined because it is expecting to find an end-of-file condition at the end of the character stream and it won't get that with a MemoryFile until it gets to the end of allocated memory buffer. This explains why you see all the diamond question marks in the logcat output.
To get a better understanding of the end-of-file behavior, you can modify readFile() like this. You will see that 'n' is the length you specify in the MemoryFile constructor.
public void readFile () {
StringBuffer strBuffer = new StringBuffer();
try {
InputStream in = memFile.getInputStream();
int b;
int n = 0;
while ((b = in.read()) != -1) {
n++;
}
Log.d(TAG, String.format("Stream contains %d bytes", n));
/***************
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String inputString;
while ((inputString = reader.readLine()) != null) {
strBuffer.append(inputString + "\n");
}
in.close();
reader.close();
Log.i(TAG, strBuffer.toString());
*******************/
} catch (IOException e) {
e.printStackTrace();
}
}
I can't explain why you see output when the read and write are in the same method, but not when they are in separate methods. Separate methods worked for me (KitKat on Samsung S3). Now that it is understood that BufferReader can't be used on a MemoryFile, the question of why it worked one way and not the other is not significant.
You may find find these MemoryFile test cases helpful as examples of its use. I didn't find any other good examples.
I think the problem is the length of the MemoryFile is not set.
memFile = new MemoryFile("MemoryFileTest", 1000000);
Try memFile = new MemoryFile("MemoryFileTest", LENGTH_OF_YOUR_STRING); Hope it helps.

Change from using a BufferedReader for a file, to a String

I have a working app that would take a text file, modify it in stages until it was neat and usable.
every stage would take in a file and modify it, then spit out a file that the next one would buffer in.
i am trying to make it cleaner so i want stop pulling in files, except the first one, and pass the output down the app as a string.
Using this code, how would i do that?
this is the second stage.
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(new File("C:/Stage_Two.txt")));
StringBuffer stringBuffer = new StringBuffer();
String line;
while ((line = bufferedReader.readLine()) != null) {
Pattern pattern = Pattern.compile("ALL|MESSAGE|Time|PAPER_MAIN|GSP");
if (pattern.matcher(line).find()) {
continue;
}
stringBuffer.append(line);
stringBuffer.append("\n");
}
BufferedWriter bwr = new BufferedWriter(new FileWriter(new File("C:/Stage_Three.txt")));
bwr.write(stringBuffer.toString());
bwr.flush();
bwr.close();
// to see in console
//System.out.println(stringBuffer);
} catch (IOException e) {
}
i have looked into InputStream, InputStreamReader, and Reader...but if its one of those i cant seem to make headway.
I'm not sure how a string would clean it up. The benefit of using readers and writers is that you don't need to have everything in memory. The following code will allow for very large files to be processed.
public void transformFile(File in, File out) throws IOException {
/*
* This method allocates the resources needed to perform the operation
* and releases them once the operation is done. This mechanism is know
* as a try-with-resource. After the try statement exits, the resources
* are closed
*/
try (BufferedReader bin = new BufferedReader(new FileReader(in));
Writer bout = new FileWriter(out)) {
transformBufferedReader(bin, bout);
}
}
private void transformBufferedReader(BufferedReader in, Writer out) throws IOException {
/*
* This method iterates over the lines in the reader and figures out if
* it should be written to the file
*/
String line = null;
while ((line = in.readLine()) != null) {
if (isWriteLine(line)) writeLine(line, out);
}
}
private boolean isWriteLine(String line) throws IOException {
/*
* This tests if the line should be written
*/
return !line.matches("ALL|MESSAGE|Time|PAPER_MAIN|GSP");
}
private void writeLine(String line, Writer writer) throws IOException {
/*
* Write a line out to the writer
*/
writer.append(line);
writer.append('\n');
}
If you insist on using string, you could add the following method.
public String transformString(String str) {
try (BufferedReader bin = new BufferedReader(new StringReader(str));
Writer bout = new StringWriter()) {
transformBufferedReader(bin, bout);
return bout.toString();
} catch (IOException e) {
throw new IllegalStateException("the string readers shouln't be throwing IOExceptions");
}
}

How to unit test a method that reads a given file

I know this is a bit naive. How to unit test this piece of code without giving physical file as input.
I am new to mockito and unit testing. So I am not sure. Please help.
public static String fileToString(File file) throws IOException
{
BufferedReader br = new BufferedReader(new FileReader(file));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append("\n");
line = br.readLine();
}
return sb.toString();
} finally {
br.close();
}
}
You can create a file as part of the test, no need to mock it out.
JUnit does have a nice functionality for creating files used for testing and automatically cleaning them up using the TemporaryFolder rule.
public class MyTestClass {
#Rule
public TemporaryFolder folder = new TemporaryFolder();
#Test
public void myTest() {
// this folder gets cleaned up automatically by JUnit
File file = folder.newFile("someTestFile.txt");
// populate the file
// run your test
}
}
You should probably refactor your method. As you realized, a method taking a file as input isn't easily testable. Also, it seems to be static, which doesn't help testability. If you rewrite your method as :
public String fileToString(BufferedReader input) throws IOException
it will be much easier to test. You separate your business logic form the technicalities of reading a file. As I understand it, your business logic is reading a stream and ensuring the line endings are unix style.
If you do that, your method will be testable. You also make it more generic : it can now read from a file, from a URL, or from any kind of stream. Better code, easier to test ...
Why do you wanna mock a file? Mocking java.io.File is a bad idea as it has loads of native stuff. I would advice you to ensure that a minimalist text file is available in classpath when the unit tests are run. You can convert this file to text and confirm the output.
you could use combination of ByteArrayInputStream and BufferedReader class, to make your required file within your code. So there wouldn't be any need to create a real File on your system. What would happen if you don't have enough permission --based of some specific circumstances -- to create a file. On the code below, you create your own desirable content of your file:
public static void main(String a[]){
String str = "converting to input stream"+
"\n and this is second line";
byte[] content = str.getBytes();
InputStream is = null;
BufferedReader bfReader = null;
try {
is = new ByteArrayInputStream(content);
bfReader = new BufferedReader(new InputStreamReader(is));
String temp = null;
while((temp = bfReader.readLine()) != null){
System.out.println(temp);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try{
if(is != null) is.close();
} catch (Exception ex){
}
}
}

Categories