I've been reading the book Beginning Android Games and I came across this code and text:
public static void load(FileIO files) {
BufferedReader in = null;
try { in = new BufferedReader(new InputStreamReader(
files.readFile(".mrnom")));
soundEnabled = Boolean.parseBoolean( in .readLine());
for (int i = 0; i < 5; i++) {
highscores[i] = Integer.parseInt( in .readLine());
}
} catch (IOException e) {
// :( It's ok we have defaults
} catch (NumberFormatException e) {
// :/ It's ok, defaults save our day
} finally {
try {
if ( in != null)
in .close();
} catch (IOException e) {}
}
}
public static void save(FileIO files) {
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(
files.writeFile(".mrnom")));
out.write(Boolean.toString(soundEnabled));
for (int i = 0; i < 5; i++) {
out.write(Integer.toString(highscores[i]));
}
} catch (IOException e) {} finally {
try {
if (out != null)
out.close();
} catch (IOException e) {}
}
}
Next up is a method called save(). It takes the current settings and serializes them to
the .mrnom file on the external storage (e.g., /sdcard/.mrnom). The sound setting and each
high-score entry is stored as a separate line in that file, as expected by the load()
method. If something goes wrong, we just ignore the failure and use the default values
defined earlier. In an AAA title, you might want to inform the user about this loading
error
I am very confused as it says it writes to a new line(in the save method) so that in the load method, which uses readLine() works properly. However, they are only using write() with no /n characters. How will this work? Is it simply a typo?
No, it's not a typo.
BufferedReader read text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines. Then, it uses as delimiter the common System.lineSeparator() to split the text values.
Check the Javadoc by yourself.
Related
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.
I have spent the last week trying to figure out how to make this stupid code work. I have managed to get everything to work except for reading from my text file. It can read an individual integer on a line, but when given a line with multiple integers separated by spaces, it freaks out. Now I've gone and tried to fix it and the code won't even compile anymore. Only one line is causing problems.
I'm not good at coding, so I don't know where to begin. Yes, I've looked this up online. Yes, I've checked the forums. Yes, I have tried multiple different methods to make this work....
How do I fix this?? :(
ArrayList<Integer> list = new ArrayList<Integer>();
// the above line is in a different method in the same class, but it's relevant here
File file = new File("C:\\Users\\Jocelynn\\Desktop\\input.txt");
BufferedReader reader = null;
try
{
reader = new BufferedReader(new FileReader(file));
String text = null;
while ((text = reader.readLine()) != null)
{
// I want the following line to read "218 150 500 330", and to store each individual integer into the list. I don't know why it won't work :(
list.add(Integer.parseInt(src.next().trim()));
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
try
{
reader.close();
}
catch (IOException e)
{
e.printStackTrace();
}
//print out the list
System.out.println(list);
Thank you for the help! I'm sure that I'm just missing something really simple...
You can use a Scanner(String) like
while ((text = reader.readLine()) != null) {
Scanner scanner = new Scanner(text);
while (scanner.hasNextInt()) {
list.add(scanner.nextInt());
}
}
Of course, your entire method could be simplified by using a try-with-resources Statement and the diamond operator and just Scanner(File) like
public static void main(String[] args) {
File file = new File("C:\\Users\\Jocelynn\\Desktop\\input.txt");
List<Integer> list = new ArrayList<>();
try (Scanner scanner = new Scanner(file);) {
while (scanner.hasNextInt()) {
list.add(scanner.nextInt());
}
} catch (Exception e) {
e.printStackTrace();
}
// print out the list
System.out.println(list);
}
Do this inside the while loop
String[] individualArray = text.split(" ");//note space
for(String individual:individualArray){
yourList.add(individual);//You need to parse it to integer here as you have already done
}
In the above code, individualArray will contain each individual integers that are separated by space. And inside the for loop each string needs to be parsed to integer and then added to your list
try this :
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
File file = new File("C:\\Users\\Jocelynn\\Desktop\\input.txt");
BufferedReader reader = null;
try
{
reader = new BufferedReader(new FileReader(file));
String text = null;
while ((text = reader.readLine()) != null)
{
// you need only this for loop in you code.
for (String value : text.split(" ")) { // get list of integer
if(!value.equals("")) // ignore space
list.add(Integer.parseInt(value)); // add to list
}
}
} catch (FileNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
try
{
reader.close();
} catch (IOException e)
{
e.printStackTrace();
}
// print out the list
System.out.println(list);
}
I have my method all ready but it just doesn't write the duplicates to my text file as its meant to do, it prints out to screen but not to the file?
// Open the file.
File file = new File("file.txt");
Scanner inputFile = new Scanner(file);
//create a new array set Integer list
Set<Integer> set = new TreeSet<Integer>();
//add the numbers to the list
while (inputFile.hasNextInt()) {
set.add(inputFile.nextInt());
}
// transform the Set list in to an array
Integer[] numbersInteger = set.toArray(new Integer[set.size()]);
//loop that print out the array
for(int i = 0; i<numbersInteger.length;i++) {
System.out.println(numbersInteger[i]);
}
for ( int myDuplicates : set) {
System.out.print(myDuplicates+",");
BufferedWriter duplicates = new BufferedWriter(new FileWriter("sorted.txt"));
try {
duplicates.write(myDuplicates + System.getProperty("line.separator"));
} catch (IOException e) {
System.out.print(e);
duplicates.close();
}
//close the input stream
inputFile.close();
}
}
This part is the one im talking about
for ( int myDuplicates : set) {
System.out.print(myDuplicates+",");
BufferedWriter duplicates = new BufferedWriter(new FileWriter("sorted.txt"));
try {
duplicates.write(myDuplicates + System.getProperty("line.separator"));
} catch (IOException e) {
System.out.print(e);
duplicates.close();
}
//close the input stream
inputFile.close();
}
}
You're only calling duplicates.close() if there's an IOException. If you don't close the writer, you won't flush any buffered data to it. You should be closing the writer in a finally block, so that you close it whether there's an exception or not.
However, you should both open and close the file outside the loop. You want the file to be open throughout the loop. You probably want:
BufferedWriter duplicates = new BufferedWriter(new FileWriter("sorted.txt"));
try {
// Loop in here, writing to duplicates
} catch(IOException e) {
// Exception handling
} finally {
try {
duplicates.close();
} catch (IOException e) {
// Whatever you want
}
}
If you're using Java 7, you can do this more simply using a try-with-resources statement.
(Also, for some reason you're calling inputFile.close() in the loop, miles after you've actually finished reading from it. Again, this should be in a finally block, when you no longer need inputFile.)
Is there a way to check whether a file was correctly written, I mean if there is an EOF at the end?
I'm asking that because I have a program that takes some file, merge them in a very big file and then use it to get statistics from it.
The point is that the second part never ends because it doesn't recognize the end of file.
The relevant parts of the code are the following:
(please do not ask for the whole code as I cannot post for important reasons)
FileWriter file=null;
PrintWriter pw = null;
String pathToRead=null;
InputStreamReader isr = null;
BufferedReader br = null ;
FileInputStream fis = null ;
TestJFileChooser d=new TestJFileChooser();
int c=1;
String line=null;
....
//here i select the files
selectedFile=new File(pathToRead);
//here I get one buffer reader for each file got with listFiles()
for(File file_sel:app){
if (file_sel.getName().startsWith("gtou")){
System.out.println(file_sel.getName());
fis = null;
try {
fis = new FileInputStream(file_sel);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
isr=new InputStreamReader(fis);
br=new BufferedReader(isr);
map.put(i, br);
num_file++;
i++;
}
}
//then I select the output file and open a print writer for it
fileToWrite=new File(pathToRead);
try {
file = new FileWriter(fileToWrite);
pw= new PrintWriter(file);
} catch (IOException e1) {
e1.printStackTrace();
}
//merging part
....
line=br.readLine();
while(line!=null){
System.out.println("line is:"+line);
....
line=br.readLine();
}
//end of merging ....
pw.flush();
pw.close();
try {
if (file!=null) file.close();
fis.close();
isr.close();
br.close();
for(int fi=0;fi<num_file;fi++){
br2=map.get(fi);
br2.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
so.kill();
Runtime r=Runtime.getRuntime();
r.gc();
//this is a popup that comes out
GlitchSquad gli=new GlitchSquad("Completed");
the problem is that as output I get:
line is: null ;
line is: null ;
line is: null ;
etc
And never get to "completed" popup =(
I cannot understand what is exactly that null because the control line!=null doesn't work.
I also tried to use that null as a string ..but nothing..
I thought that was a problem in how I close the streams but now the code seems correct to me ..but still no way to stop it..
Suggestion?
Thanks in advance!
p.s. it is a summarized version in order to focus on the streams.. variables are correctly declared and the same is for imports etc
edit: code updated
EOF is EOF. There is no more data. Unless you have an expected EOF mark within the file, or a self-describing protocol that tells you where the EOF mark should be, there is no way to determine whether the file was completely written.
I don't know if it will solve your problem, but I'd be using this code instead:
try {
fis = new FileInputStream(file_sel);
isr=new InputStreamReader(fis);
br=new BufferedReader(isr);
map.put(num_file++, br);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Otherwise there may be uncaught "NullPointer"-exceptions or strange BufferedReaders in your "map". ( I don't right now know how new InputStreamReader(null) will behave.)
It looks like i and num_file have always equal values, so just drop i. Or use a LinkedList and drop both.
If there's not a special merging that you have to do, I'd just do it like this:
OutputStream os;
try {
os = new FileOuputStream(outfile);
} catch (FileNotFoundException e) {
os = null;
e.printStackTrace();
}
if (os != null) {
for(File file_sel:app) {
if (file_sel.getName().startsWith("gtou")) {
System.out.println(file_sel.getName());
InputStream is = null;
try {
is = new FileInputStream(file_sel);
byte[] buffer = new byte[1024];
int readBytes = 0;
while ((readBytes = is.read(buffer)) > 0) {
os.write(buffer, 0, readBytes);
}
fos.flush();
is.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
If you read files with different encodings, you will have to modify at least the reading of course.
If it doesn't work, I'd suggest you build a "summarized" and runable sample program.
The core of your question is this code:
BufferedReader br = ...
String line = br.readLine();
while (line != null) {
System.out.println("line is:" + line);
...
line = br.readLine();
}
You say that this repeatedly outputs this:
line is: null ;
line is: null ;
(Notice the " ;" on the end!!!)
The only way that can happen is if the file you are reading contains at least one line that look like this:
null ;
Indeed, unless the "..." code includes a continue statement, there must must be lots of those lines in the input file.
Is there a way to check whether a file was correctly written?
Yea. Look at it using a text editor and/or check its file size.
I mean if there is an EOF at the end?
In modern file systems, EOF is a position not a marker. Specifically it is the position after the last byte of the file. So it is logically impossible for a file to not have an EOF. (You'd have to have a file that is infinite in length for there to be no EOF.)
I'm sure there is a fairly simple answer to this question, so here we go.
I'm trying to use a FileWriter to write text to a file. My program reads text in from an already existing file, specified by the user and then asks whether to print the text to the console or to a new file, also to be named by the user.
I believe my problem is with passing the FileWriter to the "FileOrConsole" method. Am I not passing or declaring the FileWriter in the "FileOrConsole" method correctly? The file is always created but nothing is written to it.
Here is the code:
import java.io.*;
import java.util.*;
public class Reader {
public static void main(String[] args) throws IOException {
Scanner s = null, input = new Scanner(System.in);
BufferedWriter out = null;
try {
System.out.println("Would you like to read from a file?");
String answer = input.nextLine();
while (answer.startsWith("y")) {
System.out.println("What file would you like to read from?");
String file = input.nextLine();
s = new Scanner(new BufferedReader(new FileReader(file)));
System.out
.println("Would you like to print file output to console or file?");
FileOrConsole(input.nextLine(), s, input, out);
System.out
.println("\nWould you like to read from the file again?");
answer = input.nextLine();
}
if (!answer.equalsIgnoreCase("yes")) {
System.out.println("Goodbye!");
}
} catch (IOException e) {
System.out.println("ERROR! File not found!");
// e.printStackTrace();
} finally {
if (s != null) {
s.close();
}
if (out != null) {
out.close();
}
}
}
public static void FileOrConsole(String response, Scanner s, Scanner input,
BufferedWriter out) {
if (response.equalsIgnoreCase("console")) {
while (s.hasNext()) {
System.out.println(s.nextLine());
}
} else if (response.equalsIgnoreCase("file")) {
System.out.println("Name of output file?");
response = input.nextLine();
try {
out = new BufferedWriter(new FileWriter(response));
} catch (IOException e) {
e.printStackTrace();
}
while (s.hasNext()) {
try {
out.write(s.nextLine());
out.newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println("Sorry, invalid response. File or console?");
response = input.nextLine();
FileOrConsole(response, s, input, out);
}
}
}
you make classic error forgetting that parameters passed by value in case of java it is a value of the reference. The thing is that your assignment
out = new BufferedWriter(new FileWriter(response));
actually does not change the variable declared in main() it stays null
BufferedWriter out = null;
and then in finally it skips the close() by the if(out==null)
and as it is Buffered and you do no flush nothing is written to file.
what you got to do is out.close(); in side the FileOrConsole method call
OR
do the out = new BufferedWriter(new FileWriter(response));
outside of it. You choose :-)
Try flushing your stream, but more importantly, remember to close it.
Here's a code example of recommended practice for handling streams. Same approach can be used for input streams too and things like database code where it's important to always clean up after yourself to get the expected results.
BufferedWriter out = null;
try {
out = // ... create your writer
// ... use your writer
} catch(IOException ex) {
// maybe there was a problem creating or using the writer
} finally {
if (null != out) {
out.flush();
out.close();
out = null;
}
}