I am trying to read a text file which contains strings (separated by commas) of airport information. However, when I try to read the file, it throws and IOException. Here is the code:
public ArrayList<ArrayList<String>> createAirportLibrary() {
ArrayList<ArrayList<String>> airportLibrary = new ArrayList<>();
String[] line;
BufferedReader reader = null;
try {
// import the text file
File airportsFile = new File("C:\\Users\\cjkei\\AndroidStudioProjects\\TravelTime\\app\\libs\\airports.txt");
// read the first line of the file
reader = new BufferedReader(new FileReader(airportsFile));
line = reader.readLine().split(",");
// loop through each line of file and add each airport to the library
while (line != null) {
int i = 0;
ArrayList<String> thisAirport = new ArrayList<>();
while (i < line.length){
if (line[i] instanceof String){
thisAirport.add(line[i]);
}
else {
airportLibrary.add(thisAirport);
thisAirport.clear();
}
i++;
}
line = reader.readLine().split(",");
}
}
catch (IOException e) {
Context context = this;
String text = "error reading file";
int duration = Toast.LENGTH_SHORT;
Toast.makeText(context, text, duration).show();
}
finally {
try {
if (reader != null) {
reader.close();
}
}
catch (IOException e) {
Context context = this;
String text = "could not close reader";
int duration = Toast.LENGTH_SHORT;
Toast.makeText(context, text, duration).show();
}
}
return airportLibrary;
}
I tried to debug step by step, but right after the onCreate call, it shows
this.
You might want to try the function Files.lines. It returns a Stream<String> you can then iterate over the stream.
Stream<String> stream = Files.lines(Paths.get(fileName))
stream.forEach(this::doSomethingWithLine);
private void doSomethingWithLine(String line) {
// actually do something
}
The picture you added does not show any exception information, but it does make clear where the error is coming from:
You are confusing two environments, and trying to open a file that does not exist.
The code in your example is for an Android app, but the file path is for a file on a Windows PC.
There is no "C drive" on Android devices, and you can not have Android code read a file from your PC, even if you run it on an emulator running on said PC.
If you look carefully at the full exception message, you will see that the problem is "File not found".
To do this, you can do something like this:
Toast.makeText(context, "Exception: " + e.toString(), Toast.LENGTH_SHORT).show();
or batter yet, since you are on Android, use the logging utility:
Log.e("MY_APP", "Exception: " + e.toString());
e.printStackTrace();
If you want the file to be part of your app and read it on the Android device, put it under assets folder in your project and use:
context.getAssets().open("MyFile.txt");
https://developer.android.com/reference/android/content/res/Resources
Related
I am trying to get a value from the first line of a csv file ( header excluded) store in Firebase Storage
Here is the code :
private String readFromCsv() {
StorageReference refCompteActifs = FirebaseStorage.getInstance().getReference().child("my_file").child("my_file.csv");
StorageReference gsReference = refCompteActifs.getStorage().getReferenceFromUrl("gs://test-8095e.appspot.com/my_file/my_filer.csv");
File localFile = null;
try {
localFile = File.createTempFile("my_file", ".csv");
} catch (IOException e) {
e.printStackTrace();
}
File finalLocalFile = localFile;
final String[] result = {null};
List<String> rows = new ArrayList<>();
gsReference.getFile(Objects.requireNonNull(localFile)).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
try {
CSVReader reader = new CSVReader(new FileReader("./data/user/0/com.example.test/cache/" + finalLocalFile.getName()), ',', '\'', 1);
String[] nextLine = null;
while ((nextLine = reader.readNext()) != null) {
System.out.println(nextLine[4] + "\n");
rows.add(nextLine[4]);
}
} catch (IOException e) {
e.printStackTrace();
}
for (int i = 0; i < rows.size(); i++) {
result[0] = rows.get(i);
}
}
}
System.out.println(result[0] + "\n");
return result[0];
}
The console never write "System.out.println(result[0] + "\n");" result[0] is affected inside the onlistener but I can't access it outside of it.
Thank you for your Help
That is the expected behavior. The getFile API is an asynchronous operation, which means that it executes in the background while the rest of your code continues to run. Then when the operation is complete, your onSuccess is called with the result.
This is easiest to see if you add some logging:
Log.i("File", "1. Starting to load file");
gsReference.getFile(Objects.requireNonNull(localFile)).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
Log.i("File", "2. Loaded file");
}
}
Log.i("File", "3. Started to load file");
If you run this code it outputs:
Starting to load file
Started to load file
Loaded file
This is probably not what you expected, but it is working by design - and it does completely explain why your System.out.println(result[0] + "\n"); doesn't show the file contents: the file hasn't been loaded yet.
This is an incredibly common problem, as most I/O and network APIs are asynchronous these days. The solution is always the same: any code that needs the data that is asynchronously loaded has to be inside the onSuccess handler, be called from there, or otherwise synchronized.
This means for example that you can't return the value from the file, as the return runs before the load has completed, and you'll instead want to pass a callback to your readFromCsv function, very similar to the OnSuccessListener.
For more on this, I recommend reading:
getContactsFromFirebase() method return an empty list
Setting Singleton property value in Firebase Listener
more questions on losing the asynchronous value outside of a callback
I have an app which gets data from an Arduino via bluetooth. The data are written into various ArrayLists and saved in files afterwards. Here is the code:
public boolean SaveValues(ArrayList<String> arrayList1, ArrayList<String> arrayList2, String valueType, String timeStart, String timeStop) {
String filename = "File_" + valueType + "_" + timeStart + " bis " + timeStop;
FileOutputStream outputStream = null;
if(arrayList1.size() == 0)
return false;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
for (int i = 0; i < arrayList1.size(); i++) {
outputStream.write(arrayList1.get(i).getBytes());
outputStream.write("\n".getBytes());
outputStream.write(arrayList2.get(i).getBytes());
outputStream.write("\n".getBytes());
}
outputStream.close();
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
I also save the valuetype, timeStart and timeStop into a database to be able to find the files. My problem is, that somehow the table where I save these values got deleted, so I am not able to find the files in the app. I would like to find the files maybe on the phone or something. Actually, I just need the filenames to be able to open them in the app, because they contain data I need. So, where can I find these files?
I have tried searching in the phones files. The files, and all the other apps data, should be saved in Android/data/package-name but I can't find the package name in Android/data. I also tried to search for "File_" in the files, because that's what every one of my files start with. But no file gets found.
I am writing a method that takes in a List of Twitter Status objects as a parameter, opens a log file containing String represenatations of Tweets, checks if any of the String representations of the Status objects are already written to the file - if so, it removes them from the list, if not it appends the Status to the file.
Everything is working up until I attempt to write to the file. Nothing is being written at all. I am led to believe that it is due to the method having the file open in two different places: new File("tweets.txt") and new FileWriter("tweets.txt, true).
Here is my method:
private List<Status> removeDuplicates(List<Status> mentions) {
File mentionsFile = new File("tweets.txt");
try {
mentionsFile.createNewFile();
} catch (IOException e1) {
// Print error + stacktrace
}
List<String> fileLines = new ArrayList<>();
try {
Scanner scanner = new Scanner(mentionsFile);
while (scanner.hasNextLine()) {
fileLines.add(scanner.nextLine());
}
scanner.close();
} catch (FileNotFoundException e) {
// Print error + stacktrace
}
List<Status> duplicates = new ArrayList<>();
for (Status mention : mentions) {
String mentionString = "#" + mention.getUser().getScreenName() + " \"" + mention.getText() + "\" (" + mention.getCreatedAt() + "\")";
if (fileLines.contains(mentionString)) {
duplicates.add(mention);
} else {
try {
Writer writer = new BufferedWriter(new FileWriter("tweets.txt", true));
writer.write(mentionString);
} catch (IOException e) {
// Print error + stacktrace
}
}
}
mentions.removeAll(duplicates);
return mentions;
}
I wrote here few thoughts looking your code.
Remember to always close the object Reader and Writer.
Have a look at try-with-resources statement :
try (Writer writer = new BufferedWriter(new FileWriter("tweets.txt", true))) {
writer.write(mentionString);
} catch (IOException e) {
// Print error + stacktrace
}
To read an entire file in a List<String>:
List<String> lines = Files.readAllLines(Paths.get("tweets.txt"), StandardCharsets.UTF_8);
And again, I think it's a bad practice write in the same file you're reading of.
I would suggest to write in a different file if you don't have a particular constraint.
But if you really want have this behavior there are few alternative.
Create a temporary file as output and, when you process is successfully completed, than move it to the old one using Files.move(from, to).
I'm trying to write to an external txt (or csv) file for Android. I can run an app, close it, and run it again, and readData() will read back to my log what I've stored. However, the dirFile (file directory) appears nowhere within my Android files (even if I connect it to a computer and search).
Something interesting, though: if I clear my log (similar to a list of print statements shown within Eclipse) and disconnect my phone from my computer, then reconnect it, the log reappears with everything I've ever written to my file (even if I later overwrote it)...yet the app isn't even running!
Here is my code. Please help me understand why I cannot find my file!
(Note: I've tried appending a "myFile.txt" extension to the directory, but it just causes an EISDIR exception.)
public void writeData(String dirName){
try
{
File root = new File(getExternalFilesDir(null), dirName);
// Writes to file
//
// The "true" argument allows the file to be appended. Without this argument (just root),
// the file will be overwritten (even though we later call append) rather than appended to.
FileWriter writer = new FileWriter(root, true);
writer.append("Append This Text\n");
writer.flush();
writer.close();
// Checks if we actually wrote to file by reading it back in (appears in Log)
//readData(dirName);
}
catch(Exception e)
{
Log.v("2222", "2222 ERROR: " + e.getMessage());
}
}
If you're interested, here's the function I wrote to read in the data:
public void readData(String dirName){
try
{
File root = new File(getExternalFilesDir(null), dirName);
// Checks to see if we are actually writing to file by reading in the file
BufferedReader reader = new BufferedReader(new FileReader(root));
try {
String s = reader.readLine();
while (s != null) {
Log.v("2222", "2222 READ: " + s);
s = reader.readLine();
}
}
catch(Exception e) {
Log.v("2222", "2222 ERROR: " + e.getMessage());
}
finally {
reader.close();
}
}
catch(Exception e) {
Log.v("2222", "2222 ERROR: " + e.getMessage());
}
}
Thanks!
even if I connect it to a computer and search
if I clear my log (similar to a list of print statements shown within Eclipse) and disconnect my phone from my computer, then reconnect it, the log reappears with everything I've ever written to my file (even if I later overwrote it).
What you are seeing on your computer is what is indexed by MediaStore, and possibly a subset of those, depending upon whether your computer caches information it gets from the device in terms of "directory" contents.
To help ensure that MediaStore indexes your file promptly:
Use a FileOutputStream (optionally wrapped in an OutputStreamWriter), not a FileWriter
Call flush(), getFD().sync(), and close() on the FileOutputStream, instead of calling flush() and close() on the FileWriter (sync() will ensure the bytes are written to disk before continuing)
Use MediaScannerConnection and scanFile() to tell MediaStore to index your file
You can then use whatever sort of "reload" or "refresh" or whatever option is in your desktop OS's file manager, and your file should show up.
This blog post has more on all of this.
public void create(){
folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES),"video");
boolean success = true;
if (!folder.exists()) {
success=folder.mkdirs();
}
if (success) {
readfile();
} else {
System.out.println("failed");
}
}
The above code will be used to crete the directory in th emobile at desired path
private void readfile() {
// TODO Auto-generated method stub
AssetManager assetManager = getResources().getAssets();
String[] files = null;
try {
files = assetManager.list("clipart");
} catch (Exception e) {
Log.e("read clipart ERROR", e.toString());
e.printStackTrace();
}
for(String filename : files) {
System.out.println("File name => "+filename);
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open("clipart/" + filename);
out = new FileOutputStream(folder + "/" + filename);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch(Exception e) {
Log.e("copy clipart ERROR", e.toString());
e.printStackTrace();
}
}}private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}}
this is my code used to write file in internal memory from the assets folder in project. This code can read all type(extension) of file from asset folder to mobile.
Don't forget to add permission in manifest file
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
and call the above function by
readfile();//this call the function to read and write the file
I hope this may help you.
Thank you.
I have this method, supposed to write an arrayList to a file:
private ArrayList<String> readFromFile() {
String ret = "";
ArrayList<String> list = new ArrayList<String>();
try {
InputStream inputStream = openFileInput("jokesBody.bjk");
if (inputStream != null) {
InputStreamReader inputStreamReader = new InputStreamReader(
inputStream);
BufferedReader bufferedReader = new BufferedReader(
inputStreamReader);
String receiveString = "";
StringBuilder stringBuilder = new StringBuilder();
while ((receiveString = bufferedReader.readLine()) != null) {
list.add(receiveString);
}
inputStream.close();
ret = stringBuilder.toString();
System.out.println("DA CRAZY FILE: " + ret);
}
} catch (FileNotFoundException e) {
Log.e("login activity", "File not found: " + e.toString());
} catch (IOException e) {
Log.e("login activity", "Can not read file: " + e.toString());
}
return list;
}
The problem with it is that it writes the values like [item1, item2, item3] and later when I need to load a the values back to a listArray it's loading the whole line at index 0. Now I have found the corerct way to write and read the arrayList, but I'm having troubles accessing teh file.
Here is the code I tried:
private void writeToFile(ArrayList<String> list) {
try {
FileOutputStream fos = new FileOutputStream("jokesBody.bjk");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(list); // write MenuArray to ObjectOutputStream
oos.close();
} catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
}
But it throws the following exception:
02-12 09:21:10.227: E/Exception(2445): File write failed: java.io.FileNotFoundException: /jokesBody.bjk: open failed: EROFS (Read-only file system)
Where is the mistake, where is the default app file location? I know that I'm missing something small, but as an android beginner, I'm not able to spot it.
Isn't this:
java.io.FileNotFoundException: /jokesBody.bjk: open failed: EROFS (Read-only file system)
the issue ? You're writing to a non-writeable area. Change where you're writing to (perhaps creating a temporary file would be a simple first step - I'm not familiar with Android but I assume this is possible)
Your file seems to be read only. You cannot write to a read only file!!!
I don't think you're actually saving the file where you think you are. Look at this tutorial on writing a file to external storage. A few things:
(1) You need to request permission in your manifest to write to external storage. If not you will end up with a read only situation.
(2) You need to get the external storage directory in your code before you write to it. This should be preceeded with a general check as to whether your file directory is writeable in the first place:
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
You can then create a specific directory for the files you want to store and store them in that location so you can find them later. For example:
public File getAlbumStorageDir(String albumName) {
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
You can then write content to the file that is returned
When you are developing for Android, you must get the OutputStream from the Context:
fos = context.openFileOutput("jokesBody.bjk", Context.MODE_PRIVATE);
An explanation about how to work with files on Android is here: Saving Files