I need some help in writing to an existing json file. I can parse the data and read from it using GSON or just json in this example. I did it this way to filter the results by id displayed on screen. So it grabs the add and searches my list of over 900 videos and then gives the ones selected. Only issue is i don't want to display them i want to save them :)
final Button button = findViewById(R.id.buttonx);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// load json parse json and grab fields...
// then write to new file!
try {
//Load File
BufferedReader jsonReader = new BufferedReader(new InputStreamReader(getResources().openRawResource(R.raw.movielist)));
StringBuilder jsonBuilder = new StringBuilder();
for (String line = null; (line = jsonReader.readLine()) != null;) {
jsonBuilder.append(line).append("\n");
}
//Parse Json
JSONTokener tokener = new JSONTokener(jsonBuilder.toString());
JSONArray jsonArray = new JSONArray(tokener);
ArrayList<String> fields = new ArrayList<String>();
for (int index = 0; index < jsonArray.length(); index++) {
//Set both values into the listview
JSONObject jsonObject = jsonArray.getJSONObject(index);
String series = jsonObject.getString("id");
if (series.equals(tvId.getText())) {
fields.add(jsonObject.getString("movie"));
fields.add(jsonObject.getString("year"));
fields.add(jsonObject.getString("duration"));
fields.add(jsonObject.getString("director"));
fields.add(jsonObject.getString("image"));
fields.add(jsonObject.getString("id"));
}
}
} catch (FileNotFoundException e) {
Log.e("jsonFile", "file not found");
} catch (IOException e) {
Log.e("jsonFile", "ioerror");
} catch (JSONException e) {
Log.e("jsonFile", "error while parsing json");
}
Toast.makeText(DetailActivity.this, "The following movie has been saved " + tvId.getText(), Toast.LENGTH_LONG).show();
// Toast.makeText(DetailActivity.this, "This features is not working", Toast.LENGTH_LONG).show();
}
});
My issue is once I get the data I want to be able to write this to an existing JSON file. my api is 18 so can't use FILEwriter i am trying to make the app available to pretty much everyone. A point in the right direction would be great.
If you want to write to a file packaged in the raw folder, you will have to copy it to the local file system first. Resources contained in your raw directory in your project will be packaged inside your APK and will not be writeable at runtime. Consider looking at the Internal or External Data Storage APIs.
Update raw resources is not possible
Related
Is it possible to write a whole shared_preferences.xml at once?
I want to realize a kind of settings import/export, so i need to read and write the whole file without loosing the xml-tags.
Reading the file is easy, but when i write my values (using PrintWriter) the old values stored in memory overwrite them seconds later.
what can i do to prevent that without writing single values using preference editor.
Now I read it from a file designed like Android's own preferences.xml and write it successively in my own function like this:
public static void preferencesImport(String PreferenceFilepath) {
preferencesImportPreferenceFilepath = PreferenceFilepath;
try {
// Parsing
// see http://theopentutorials.com/tutorials/android/xml/android-simple-xml-dom-parser/
XMLParserHelper parser = new XMLParserHelper(); // reference to described XMLDOMParser helper class
BufferedInputStream stream;
try {
stream = new BufferedInputStream(new FileInputStream(preferencesImportPreferenceFilepath));
org.w3c.dom.Document doc = parser.getDocument(stream);
// string value
NodeList nodeListString = doc.getElementsByTagName("string");
for (int i = 0; i < nodeListString.getLength(); i++) {
Element eString = (Element) nodeListString.item(i);
Pref.setString(eString.getAttribute("name"), eString.getTextContent()); // Own getter/setter -> use Android's preference manager instead in similar way
}
// repeat code above for boolean, long, int, float values
stream.close();
} catch (IOException e1) {
// output IOException
} catch (Throwable t1) {
// output Throwable1
}
writer.close();
} catch (Throwable t2) {
// output Throwable2
}
}
Keep getting ArrayIndexOutOfBoundsException when trying to display a specific item form array list data displays fine in logcat but then after displaying throws exception at top please help is the code kind of new to android
public void loadData(){
InputStream file = ourContext.getResources().openRawResource(R.raw.cashpot);
BufferedReader reader = new BufferedReader(new InputStreamReader(file));
String line ="";
ArrayList<String> values = new ArrayList<String>();
try {
while((line = reader.readLine()) != null) {
values.add(line);
// String[] strings = line.split(",");
/*for(String s : strings) {
values.add(s);
}*/
}
reader.close();
//for(String s : values) Log.d("CSV Test", s);
for(int i = 0; i < values.size();i++){
String[] data = values.get(i).split(",");
Log.d("Test String",data[2] );
}
} catch (IOException e) {
e.printStackTrace();
}
}
Your some lines do not have comma(,)(or 1 comma) and you are trying to split them by comma and storing it in to data array. and you are accessing data[2] location. which might not been created that's why you are getting this exception.
There might not be a 3rd element in your array ,that is created after the split on ",".
You can print value of data before accessing data[2](that might not exist).
Or you can Debug your program and proceed step by step and monitoring the value of each variable.
I am desperatly trying to fix a bug that:
always happens in my emulator for Android versions 2.2, 2.3
never happens in emulator android versions 4.*
never happens in a real device (android 4.*)
It is the following IndexOutOfBoundsException exception:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{<myapppackage>}: java.lang.IndexOutOfBoundsException:
Invalid index 39, size is 0
In my app I am fecthing data from a json file that I am displaying as text. I've isoleted where the bug is coming from, it is when I call this method:
public String getItemValue(int id, String s) {
List<JsonItems> list = new ArrayList<JsonItems>();
try {
// CONVERT RESPONSE STRING TO JSON ARRAY
JSONArray ja = new JSONArray(s);
// ITERATE THROUGH AND RETRIEVE
int n = ja.length();
for (int i = 0; i < n; i++) {
// GET INDIVIDUAL JSON OBJECT FROM JSON ARRAY
JSONObject jo = ja.getJSONObject(i);
// RETRIEVE EACH JSON OBJECT'S FIELDS
JsonItems ji = new JsonItems();
ji.id = jo.getInt("id");
ji.text= jo.getString("text");
list.add(ji);
}
} catch (Exception e) {
e.printStackTrace();
}
return list.get(id).text;
}
My class JsonItems is very basic:
public class JsonItems{
int id;
String text;
}
Sample from my json file:
[
{"id":0,"text":"some text 0"},
{"id":1,"text":"some text 1"},
{"id":2,"text":"some text 2"}
]
Here is how I process content of my json file into a String
public static String fromJsonFileToString(String fileName, Context c) {
//JSONArray jArray = null;
String text = "";
try {
InputStream is = c.getAssets().open(fileName);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
text = new String(buffer);
} catch (IOException e) {
throw new RuntimeException(e);
}
return text;
}
Once again I repeat: the IndexOutOfBoundsException NEVER happens on a device with Android 4.* , it only happens when I test the app on emulators with Android 2.*
Any idea where it is coming from?
Thanks
First problem:
You are not reading your input stream correctly. Calling available literally does just that - it returns you the amount of data that is available to be read, when the call is made. This number may, or may not represent the entire content of the file.
Reading material for you:
How to Read a File in Java.
Writing and Creating Files
Note that there are helper libraries like Apache Commons IO that make it possible to read file contents in a single line of code (IOUtils.toString(inputStream)). Android doesn't support Java 7 yet but a noteworthy alternative is available in that release, with the Files.readAllLines method. In any case, you can make the below shown changes to your file reading code and it should work better:
public static String fromFileToString(String fileName, Context context) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
context.getAssets().open(fileName)));
String line = null;
StringBuilder builder = new StringBuilder(1024);
while ((line = reader.readLine()) != null) {
builder.append(line);
}
return builder.toString();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Second problem:
You do not do any bound check, to make sure that the argument you pass into your 'search' method:
public String getItemValue(int id, String s)
Does not exceed the length of the list of items you eventually calculate:
return list.get(id).text;
// ^
// -------------
// 'id' could be larger than the list size!
In any case, your current design doesn't at all match what you are really trying to do, aka, to determine the element in the JSON array that has an 'id' field matching what you supply to the method. You need to process the JSON data as a map, in order to be able to do this.
public String getItemValue(int id, String json) {
if(json == null || json.trim().equals("")) return null;
Map<Integer, JsonItems> map = new HashMap<Integer, JsonItems>(4);
try {
JSONArray ja = new JSONArray(json);
int n = ja.length();
for (int i = 0; i < n; i++) {
JSONObject jo = ja.getJSONObject(i);
JsonItems ji = new JsonItems();
ji.id = jo.getInt("id");
ji.text = jo.getString("text");
map.put(Integer.valueOf(ji.id, ji);
}
} catch(NumberFormatException nfe) {
throw new IllegalArgumentException("Invalid JSON format");
} catch (Exception e) {
throw new RuntimeException(e);
}
JsonItems item = map.get(id);
return item != null ? item.text : null;
}
Some quick notes:
JsonItems should be called JsonItem, to conform to good Java naming standards
You should really parse and store your JSON just once, to improve performance
You are really only using a minimal subset of your JSON data, you could actually determine the matching node within your for loop and directly return its value, without having to use an intermedia Java bean object
I'm trying to read excel contents in android, but always get file not found exception
The project is in:
C:\AndroidWorkSpace\AntenaProject
And the code is:
public void TestClick(View view)
{
File inputWorkbook = new File("shidur.xls");
Workbook w;
StringBuilder sb = new StringBuilder("starting");
try {
w = Workbook.getWorkbook(inputWorkbook);
// Get the first sheet
Sheet sheet = w.getSheet(0);
// Loop over first 10 column and lines
for (int j = 0; j < sheet.getColumns(); j++) {
for (int i = 0; i < sheet.getRows(); i++) {
Cell cell = sheet.getCell(j, i);
//CellType type = cell.getType();
sb.append(cell.getContents());
}
}
} catch (Exception e) {
e.printStackTrace();
}
TextView tv = (TextView)findViewById(R.id.testText);
tv.setText(sb.toString());
}
i tried to put shidur.xls in the following folders:
C:\AndroidWorkSpace\AntenaProject\res\raw
C:\AndroidWorkSpace\AntenaProject\res
but still getting this exception.
i'm using jxl.jar from http://jexcelapi.sourceforge.net/
thanks for the help
The path that you provide to the File constructor needs to be the absolute path of the file, or you need to use the overload that takes another File object as the first parameter which represents the directory the file lives in.
That being said, constructing a file in this way is for files that are either in local storage (ie. phone's main memory) or external storage (ie. SD card).
To open a file from the res/raw directory, get an InputStream in the following way
InputStream in = getResources().openRawResource(R.raw.file_name);
Then, you will need code that reads the contents of your input stream. I use a static helper method that looks like this, but this could run you into problems if the file is huge. Hasn't happened to me yet, but in principle that's always a risk when loading the entire content of a file into memory
public static String readStream(InputStream in)
{
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder sb = new StringBuilder();
String line = null;
try
{
while((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
}
catch(Exception ex) { }
finally
{
// NOTE: you don't have my IOUtils class,
// but all these methods do is check for null and catch the exceptions that Closeable.close() can throw
IOUtils.safeClose(in);
IOUtils.safeClose(reader);
}
return sb.toString();
}
You should use the following code to open file in the /res/raw
getResources().openRawResource(R.raw.shidur.xls)
I have a CSV file in drawable/asset folder. In the CSV file there are four columns. First one is for date and rest three are for integer data.
I need to parse this CSV file and save the data in separate arrays.
I have searched for a solution, but I don't get proper idea on how to do this.
I like this csv reader: https://mvnrepository.com/artifact/net.sf.opencsv/opencsv/2.3
Just add it to your project.
Example code (assuming there is the file assets/test.csv):
String next[] = {};
List<String[]> list = new ArrayList<String[]>();
try {
CSVReader reader = new CSVReader(new InputStreamReader(getAssets().open("test.csv")));
while(true) {
next = reader.readNext();
if(next != null) {
list.add(next);
} else {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
You can access the imported data with, for example,
list.get(1)[1]
That would return a string.