Streaming to write Json - java

I have a large set of JsonObjects inside a ArrayList. I need to add these JsonObjects into a JsonArray and write it into a file. I am using Gson and below is my code.
private void myWriter(List<JsonObject> jsonObjectHolder, int number) throws IOException
{
System.out.println("Starting to write the JSON File");
//Add everything into a JSONArray
JsonArray jsonArrayNew = new JsonArray();
for(int i=0;i<jsonObjectHolder.size();i++)
{
//System.out.println("inside array: "+i);
JsonObject o = jsonObjectHolder.get(i);
System.out.println("inside array "+i+": "+o.get("title"));
jsonArrayNew.add(jsonObjectHolder.get(i));
}
System.out.println("Size: "+jsonArrayNew.size());
//Write it to the File
File file= new File("items.json");
FileWriter fw = new FileWriter(file);;
fw.write(jsonArrayNew.toString());
fw.flush();
fw.close();
System.out.println("outside array");
}
I don't like this way. The ArrayList holds lot of data and the way I write could generate OutOfMemoryError. Instead, I would like to Stream and write these to the file.
Update
According to the answer of SO user "Alden", here how I edited the code.
private void myWriter(List<JsonObject> jsonObjectHolder) throws IOException
{
JsonWriter writer = new JsonWriter(new FileWriter(new File("items.json")));
Gson gson = new Gson();
writer.beginArray();
for (JsonObject jsonObject : jsonObjectHolder)
{
gson.toJson(jsonObject, writer);
}
writer.endArray();
writer.close();
}
Please let me know whether this is the correct way of doing it.

You can use Gson to stream your list like this:
private void myWriter(List<JsonObject> jsonObjectHolder, Gson gson) throws IOException
{
JsonWriter writer = new JsonWriter(new FileWriter(new File("items.json")));
writer.beginArray();
for (JsonObject jsonObject : jsonObjectHolder)
{
gson.toJson(jsonObject, writer);
}
writer.endArray();
writer.close();
}
This assumes you have a Gson instance that you can use. If you do not, you can use writer.beginObject() with writer.endObject() and manually add properties to the writer, but I wouldn't recommend this because you've already done the work of building a JsonObject.

Related

How to write an ArrayList into a text file in Android App

So I have an ArrayList of some data which is needed for the app, and I don't have any problem to load the data from a text file named MyData.txt and store it in an ArrayList.
But the problem is, after some changes in the data which is stored in loaded ArrayList by the user I want the data that stored into the MyData.txt get updated with the new ArrayList.
I write some codes for that but it doesn't seem to work and my txt file is not getting updated after I press the save button, it just jumped out of the app.
public void SaveData(List<Four> list) throws IOException {
FileOutputStream file = openFileOutput("MyData.txt", MODE_PRIVATE);
OutputStreamWriter outputFile = new OutputStreamWriter(file);
for(int i=0 ; i<list.size() ; i++){
outputFile.write(list.get(i).first+";"+list.get(i).second+";"+list.get(i).second+";"+list.get(i).fourth+"\n");
}
outputFile.flush();
outputFile.close();
}
I have an ArrayList with the data type of Four ( Four is a class which includes "String(showed as first), String(showed as second, int (showed as third), int (showed as fourth))
the output of the code should be stored in a text file, for example, if My list just had one index like "John Brown 1938494 0" my text file should look like "John;Brown;1938494;0".
if you need to know anything else about the code just tell me. thanks for your time.
You can use google gson.
class Four {
String first,second;
int third,fourth;
public Four()
{
}
}
//save_array(your_context,"MyData.txt",your_array)
void save_array(Context contxt,String file_name,ArrayList<Four> testes)
{
Gson gson = new Gson();
String json = gson.toJson(testes);
String root = contxt.getExternalFilesDir(null).getAbsolutePath() + "/arrays";
File file = new File(root);
file.mkdirs();
try {
File out_file = new File(file, file_name);
if(out_file.exists()){
out_file.delete();
}
FileWriter writer = new FileWriter(out_file,true);
writer.append(json);
writer.flush();
writer.close();
}catch (Exception ex)
{
}
}
ArrayList<Four> saved_array(Context contxt, String file_name) throws IOException {
String path = contxt.getExternalFilesDir(null).getAbsolutePath() + "/arrays/"+file_name;
Gson gson = new Gson();
BufferedReader br = new BufferedReader(new FileReader(path));
return gson.fromJson(br, new TypeToken<List<Four>>(){}.getType());
}
you can call as
Remember to request for storage permissions

Writing multiple times on a JSON file with Java

I'm trying to write multiple times on a JSON file using JSON-Simple and Java, but I have some problems after the second run. I'm new to JSON so that's just a way to learn about it, here is the code:
public class Writer{
#SuppressWarnings("unchecked")
public static void main(String[] args) throws IOException {
JSONParser parser = new JSONParser();
JSONObject outer = new JSONObject();
JSONObject inner = new JSONObject();
JSONObject data = new JSONObject();
ArrayList<JSONObject> arr = new ArrayList<JSONObject>();
inner.put("Name", "Andrea");
inner.put("Email", "andrea#mail.com");
arr.add(inner);
outer.put("Clienti", arr);
System.out.println("Dati: " + outer);
File file = new File("temp.json");
if(file.exists()) {
PrintWriter write = new PrintWriter(new FileWriter(file));
Iterator<JSONObject> iterator = arr.iterator();
while(iterator.hasNext()) {
JSONObject it = iterator.next();
data = (JSONObject) it;
}
arr.add(data);
outer.put("Clienti", arr);
System.out.println("Dati: " + outer);
write.write(outer.toString());
write.flush();
write.close();
} else {
PrintWriter write = new PrintWriter(new FileWriter(file));
write.write(outer.toString());
write.flush();
write.close();
}
}
}
So, I just wanna try to add the same thing without losing what I added before, but when I run:
The first run goes well, it prints normally on the file.
Result:
Dati: {"Clienti":[{"Email":"andrea#gmail.com","Nome":"Andrea"}]}
The second run too, it adds another field inside the list, keeping the first one too.
Result:
Dati:
{"Clienti":[{"Email":"andrea#gmail.com","Nome":"Andrea"},{"Email":"andrea#gmail.com","Nome":"Andrea"}]}
From the third run it doesn't upload anymore the file, instead of adding another field to the existent 2 it just prints the second result.
I tried many options but still can't understand how to add a third field without losing the previous two, how can i solve this?
Solved putting this on if clause:
if(file.exists()) {
Object obj = parser.parse(new FileReader("temp.json"));
JSONObject jsonObject = (JSONObject) obj;
JSONArray array = (JSONArray) jsonObject.get("Clienti");
PrintWriter write = new PrintWriter(new FileWriter(file));
Iterator<JSONObject> iterator = array.iterator();
while(iterator.hasNext()) {
JSONObject it = iterator.next();
data = (JSONObject) it;
System.out.println("Data" + data);
arr.add(data);
}
arr.add(inner);
System.out.println(arr);
outer.put("Clienti", arr);
System.out.println("Dati: " + outer);
write.write(outer.toString());
write.flush();
write.close();
}

Making Data Structure Persistent

I read a file in JAVA and based on the users specifications, I convert the data in to a Linked List or a Tree, but how can I save the data in to the file (as a data structure), so that next time I read the data I do not have to make extra effort to parse the file.
You can save the data like this into file it is not a linked list but it will help to understand
//save persons
public void savePersons(){
try{
PersonsInfo p;
String line;
FileWriter fw= new FileWriter("input.txt");
PrintWriter pw= new PrintWriter(fw);
for (int i=0 ; i<persons.size();i++){
p =(PersonsInfo)persons.get(i);
line = p.getName() +","+ p.getAddress() +","+ p.getPhoneNum();
pw.println(line);
}
pw.flush();
pw.close();
fw.close();
} catch (IOException ioEx){
System.out.println(ioEx);
}
and you can retrieve the data like this and you dont need the parse the file every time
public class AddressBook{
ArrayList<PersonsInfo> persons;
public AddressBook (){
persons = new ArrayList <PersonsInfo> ();
loadPersons();
}
//Load Person
public void loadPersons (){
String tokens[]=null;
String name,address,phoneNum;
try{
FileReader fr= new FileReader("input.txt");
BufferedReader br= new BufferedReader(fr);
String line=br.readLine();
while (line !=null)
{
tokens = line.split(",");
name=tokens[0];
address=tokens[1];
phoneNum=tokens[2];
PersonsInfo p = new PersonsInfo(name,address,phoneNum);
persons.add(p);
line = br.readLine();
}
br.close();
fr.close();
}catch (IOException ioEx) {
System.out.println(ioEx);
}
}
It depends on how you want to store the data:
If you don't want to data to be stored in human readable form then you can go ahead with Serialization (example here). Java will take care of storing/constructing the objects/structures during write/read operations respectively.
If you want to store the data in human readable form then you can convert the data into let's say json and store it in String format. You can use Jackson's ObjectMapper class, e.g.:
ObjectMapper mapper = new ObjectMapper();
YourClass object = new YourClass();
FileOutputStream outputStream = new FileOutputStream("path_to_file");
outputStream.write(mapper.writeValueAsBytes(object));
//Read
YourClass persisted = mapper.readValue("path_to_file", YourClass.class);
Here's the example and here's Jackson's documentation.
You can use serialization which is a Java feature so very easy to use :
Save :
ObjectOutputStream oos = null;
try {
LinkedList<String> list = new LinkedList<>();
list.add("toto"); list.add("tata");
oos = new ObjectOutputStream(new FileOutputStream("C:\\Users\\..\\Doc\\list.ser"));
oos.writeObject(list);
} catch ... {
}finally (oos.close) ...{
}
Of course, if it's not a you change LinkedList to whatever you want
Load :
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("C:\\Users\\..\\Doc\\list.ser"));
final LinkedList<String> list = (LinkedList<String>) ois.readObject();
System.out.println(list.toString()); //[toto,tata]
} catch ... {
}finally (ois.close) ...{
}
At writing you use writeObject and at reading you use readObject + casting to the good type (so the order is important, if you write a List then String then Other, you may read List then String then Other)
Serialization Details

Write Array of String Arrays to File (txt,csv, etc)

I have an Arraylist of String Arrays called NewArray.
ArrayList<String[]> NewArray = new ArrayList<String[]>();
The data in NewArray looks somewhat like
[Vial1,Dest1]
[Vial2,Dest1]
[Vial3,Dest2]
[Vial4,Dest2]
I want to save this data, in this format (without the brackets) to a CSV/text file (with headers). The ideal output format would be:
VialNo,DestinationNo (these are the headers)
Vial1,Dest1
Vial2,Dest1
Vial3,Dest2
Vial4,Dest2
How would I use something like FileWriter to obtain that desired output in a txt/CSV file?
I've tried something like
FileWriter writer = new FileWriter("output.txt");
for(String[] str: NewArray) {
writer.write(str);
}
writer.close();
But I'm getting the error "The method write(int) in the type OutputStreamWriter is not applicable for the arguments (String[])"
public static void main(String[] args) throws Exception {
// initialize
ArrayList<String[]> list = new ArrayList<String[]>();
list.add(new String[] {"Vial1","Dest1"});
list.add(new String[] {"Vial2","Dest2"});
list.add(new String[] {"Vial3","Dest3"});
list.add(new String[] {"Vial4","Dest4"});
// writer
FileWriter writer = new FileWriter("output.txt");
// headers
writer.write("VialNo,DestinationNo\n");
writer.flush();
// data
for(String[] arr: list) {
String appender = "";
for(String s : arr){
writer.write(appender + s);
appender = ",";
}
writer.write("\n");
writer.flush();
}
writer.close();
}
This gave me the output
VialNo,DestinationNo
Vial1,Dest1
Vial2,Dest2
Vial3,Dest3
Vial4,Dest4
You need to loop over each string in each array, not try to simply print out the array. I also used an appender for formatting the file as a csv.
Updated code to include creating the headers
I would suggest you loop through your array and always write a line. Better put your writer in a using, so you don't have to bother with closing and flushing Streams, Writers etc.
If you actually want to save the object and not just write the content of the array down, then take a look at the serializer which outputs the object as xml which you can save to a file and load through a deserialize.
In case the accepted answer didn't work for someone (didn't for me). Try this for
ArrayList of specific class types foe example ArrayList tester = new ArrayList();
public class PassDataToFile {
public static void main(String[] args) throws IOException {
try {
RSSFeedParser parser = new RSSFeedParser("http://feeds.reuters.com/reuters/technologysectorNews");
Feed feed = parser.readFeed();
String input = "C:\\Users\\Special\\workspace\\demo.txt";
File newFile = new File(input);
if (!newFile.exists()){
newFile.createNewFile();
}
FileWriter writer = new FileWriter(newFile.getAbsoluteFile());
int sx = feed.getMessages().size();
for (int i = 0; i < sx; i++) {
writer.write(feed.getMessages().get(i).toString() + "\n");
}
writer.close();
System.out.println("File successfully written into " + input);
} catch (IOException e) {
System.out.println("File writing operation failed ");
e.printStackTrace();
}
}
}

Convert a .json file to a JSONArray

I used cURL to get some twitter feeds in the form of a json file ("twitter-feed.json"). I want to convert this json file to a JSONArray object. How do I do it?
I am new to Java and json. Your suggestions are most welcome.
FileInputStream infile = new FileInputStream("input/twitter-feed.json");
// parse JSON
JSONArray jsonArray = new JSONArray(string);
// use
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
System.out.println(jsonObject.getString("id"));
System.out.println(jsonObject.getString("text"));
System.out.println(jsonObject.getString("created_at"));
}
Thanks,
PD.
You need to read the file first, convert it to String then feed it to the JSONArray (I am assuming that you are using the JSON-Java Project. The code below illustrates how to read the file and set it to JSONArray
// read the source file, source comes from streaming API delimited by newline
// done by curl https://stream.twitter.com/1/statuses/sample.json?delimited=newline -utwitterUsername:twitterPasswd
// > /Projects/StackOverflow/src/so7655570/twitter.json
FileReader f = new FileReader("/Projects/StackOverflow/src/so7655570/twitter.json");
BufferedReader br = new BufferedReader(f);
ArrayList jsonObjectArray = new ArrayList();
String currentJSONString = "";
// read the file, since I ask for newline separation, it's easier for BufferedReader
// to separate each String
while( (currentJSONString = br.readLine()) != null ) {
// create new JSONObject
JSONObject currentObject = new JSONObject(currentJSONString);
// there are more than one way to do this, right now what I am doing is adding
// each JSONObject to an ArrayList
jsonObjectArray.add(currentObject);
}
for (int i = 0; i < jsonObjectArray.size(); i++) {
JSONObject jsonObject = jsonObjectArray.get(i);
// check if it has valid ID as delete won't have one
// sample of JSON for delete :
// {"delete":{"status":{"user_id_str":"50269460","id_str":"121202089660661760","id":121202089660661760,"user_id":50269460}}}
if(jsonObject.has("id")) {
System.out.println(jsonObject.getInt("id"));
System.out.println(jsonObject.getString("text"));
System.out.println(jsonObject.getString("created_at") + "\n");
}
}
Steps explanation :
Stream API does not provide valid JSON as a whole but rather a valid one specified by the delimited field. Which is why, you can't just parse the entire result as is.
In order to parse the JSON, I use the delimited to use newline since BufferedReader has a method readLine that we could directly use to get each JSONObject
Once I get each valid JSON from each line, I create JSONObject and add it to the ArrayList
I then iterate each JSONObject in the ArrayList and print out the result. Note that if you want to use the result immediately and don't have the need to use it later, you can do the processing itself in while loop without storing them in the ArrayList which change the code to:
// read the source file, source comes from streaming API
// done by curl https://stream.twitter.com/1/statuses/sample.json?delimited=newline -utwitterUsername:twitterPasswd
// > /Projects/StackOverflow/src/so7655570/twitter.json
FileReader f = new FileReader("/Projects/StackOverflow/src/so7655570/twitter.json");
BufferedReader br = new BufferedReader(f);
String currentJSONString = "";
// read the file, since I ask for newline separation, it's easier for BufferedReader
// to separate each String
while( (currentJSONString = br.readLine()) != null ) {
// create new JSONObject
JSONObject currentObject = new JSONObject(currentJSONString);
// check if it has valid ID as delete status won't have one
if(currentObject.has("id")) {
System.out.println(currentObject.getInt("id"));
System.out.println(currentObject.getString("text"));
System.out.println(currentObject.getString("created_at") + "\n");
}
}
You may try Gson:
For just arrays you can use:
Gson gson = new Gson();
//(Deserialization)
int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class);
To deserialize an array of objects, you can just do:
Container container = new Gson().fromJson(json, Container.class);
As shown here
Use ObjectMapper Class from jackson library like this :
//JSON from file to Object
Staff obj = mapper.readValue(new File("c:\\file.json"), Staff.class);
//JSON from URL to Object
Staff obj = mapper.readValue(new URL("http://mkyong.com/api/staff.json"), Staff.class);
//JSON from String to Object
Staff obj = mapper.readValue(jsonInString, Staff.class);

Categories

Resources