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.
Related
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.
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.
I'm creating a mini program that deletes Files using the File.delete() method but I'm having a little bit of an issue if I use the buffered Reader to read the .txt file before I delete it, it doesn't delete the file. I did come up with a solution for it: I just close the buffered reader before I delete the file. however this doesn't make sense to me as to why this is happening can anyone explain this.
import java.io.*;
import java.nio.file.Files;
public class Purge {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String sample;
boolean result = false;
BufferedReader amg = new BufferedReader(new FileReader("C:/Users/Steven/Desktop/me.txt"));
sample = amg.readLine();
amg.close();// closes the buffered reader
System.out.println("Haha I'm stille here: "+sample);
File anesu = new File("C:/Users/Steven/Desktop/me.txt");
if (anesu.exists()){
try{result = anesu.delete();
}catch( Exception x){
System.out.println("Problem Deleting File"+x);
}
catch( Throwable e){
System.out.println("Problem Deleting File Throwable"+e);
}
}else{
System.out.println("No File ");
}
System.out.println("File has been deleted: "+result);
}
}
When a stream object is garbage collected, its finalizer closes the underlying file descriptor. So, the fact that the delete only works when you added the System.gc() call is strong evidence that your code is somehow failing to close some stream for the file. It may well be a different stream object to the one that is opened in the code that you posted.
Note :
Properly written stream handling code uses a finally block to make sure that streams get closed no matter what.
If you does not want to use System.gc(), read your content with FileInputStream
InputStream in = new FileInputStream(new File("C:/temp/test.txt"));
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder out = new StringBuilder();
try {
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
}
System.out.println(out.toString()); //Prints the string content read from input stream
}
catch(Exception ex) {//TODO}
finally {
reader.close();
}
You can delete the file in the finally block.
A downside to this approach is that if an exception is thrown the file will still be deleted.
public Stream<String> readLines(Path archive) {
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
(new FileInputStream(archive.toFile()))));
return bufferedReader.lines();
} catch (IOException e) {
throw new UncheckedIOException(e);
} finally {
try {
Files.delete(archive);
System.out.println("Deleted: " + archive);
} catch (IOException e) {
System.out.println("Unable to delete: " + archive);
}
}
}
I have a text file called "high.txt". I need the data inside for my Android app. But I have absolutely no idea how to read it into an ArrayList of the Strings. I tried the normal way of doing it in Java but apparently that doesn't work in Android since it cant find the file. So how do I go about doing this? I have put it in my res folder. But how do you take the input stream that you get from opening the file within Android and read it into an ArrayList of Strings. I am stuck on that part.
Basically it would look something like this:
3. What do you do for an upcoming test?
L: make sure I know what I'm studying and really review and study for this thing. Its what Im good at. Understand the material really well.
CL: Time to study. I got this, but I really need to make sure I know it,
M: Tests can be tough, but there are tips and tricks. Focus on the important, interesting stuff. Cram in all the little details just to get past this test.
CR: -sigh- I don't like these tests. Hope I've studied enough to pass or maybe do well.
R: Screw the test. I'll study later, day before should be good.
This is for a sample question and all the lines will be stored as separate strings in the array list.
If you put the text file in your assets folder you can use code like this which I've taken and modified from one of my projects:
public static void importData(Context context) {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(context.getAssets().open("high.txt")));
String line;
while ((line = br.readLine()) != null) {
String[] columns = line.split(",");
Model model = new Model();
model.date = DateUtil.getCalendar(columns[0], "MM/dd/yyyy");
model.name = columns[1];
dbHelper.insertModel(model);
}
} catch (IOException e) {
e.printStackTrace();
}
}
Within the loop you can do anything you need with the columns, what this example is doing is creating an object from each row and saving it in the database.
For this example the text file would look something like this:
15/04/2013,Bob
03/03/2013,John
21/04/2013,Steve
If you want to read file from External storage than use below method.
public void readFileFromExternal(){
String path = Environment.getExternalStorageDirectory().getPath()
+ "/AppTextFile.txt";
try {
BufferedReader reader = new BufferedReader(new FileReader(path));
String line, results = "";
while( ( line = reader.readLine() ) != null)
{
results += line;
}
reader.close();
Log.d("FILE","Data in your file : " + results);
} catch (Exception e) {
}
}
//find all files from folder /assets/txt/
String[] elements;
try {
elements = getAssets().list("txt");
} catch (IOException e) {
e.printStackTrace();
}
//for every files read text per line
for (String fileName : elements) {
Log.d("xxx", "File: " + fileName);
try {
InputStream open = getAssets().open("txt/" + fileName);
InputStreamReader inputStreamReader = new InputStreamReader(open);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line = "";
while ((line = bufferedReader.readLine()) != null) {
Log.d("xxx", line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
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.)