ObjectOutputStream.writeUTF writes corrupt characters at the start - java

this is my .json file:
{"Usuarios":[{"password":"admin","apellido":"Admin","correo":"Adminadmin.com","direccion":"Admin","telefono":"Admin","nombre":"Admin","username":"admin"}]}
(I tried to translate my code from Spanish to English in the comments as best I could <3)
The function that writes in the JSON is this one:
public void agregarUsuario(String nombre, String apellido, String direccion, String telefono, String correo, String username, String password) {
try {
//String jsonString = JsonObject.toString();
JSONObject usuarios = getJSONObjectFromFile("/usuarios.json");
JSONArray listaUsuario = usuarios.getJSONArray("Usuarios");
JSONObject newObject = new JSONObject();
newObject.put("nombre", nombre);
newObject.put("apellido", apellido);
newObject.put("direccion", direccion);
newObject.put("telefono", telefono);
newObject.put("correo", correo);
newObject.put("username",username);
newObject.put("password", password);
listaUsuario.put(newObject);
usuarios.put("Usuarios",listaUsuario);
ObjectOutputStream outputStream = null;
outputStream = new ObjectOutputStream(new FileOutputStream("C:\\Users\\Victor\\eclipse-workspace\\Iplane\\assets\\usuarios.json"));
outputStream.writeUTF(usuarios.toString());
outputStream.flush();
outputStream.close();
}catch(JSONException e) {
e.printStackTrace();
}catch(Exception e) {
System.err.println("Error writting json: " + e);
}
So, if in my "create user" JFrame window ,I create a new user with "asdf" as info within all the user's details, I should get the following JSON file:
{"Usuarios":[{"password":"admin","apellido":"Admin","correo":"Adminadmin.com","direccion":"Admin","telefono":"Admin","nombre":"Admin","username":"admin"},{"password":"asdf","apellido":"asdf","correo":"asdf","direccion":"asdf","telefono":"asdf","nombre":"asdf","username":"asdf"}]}
And yes! that happens! but I got also, some weird ascii/Unicode symbols in front if my JSON main object. I cant copy the output here, so this is my output on imgur: link.
Why this problem happens? how could I fix it?
If someone need my json file reader (maybe the problem is there) here you go:
public static InputStream inputStreamFromFile(String path) {
try {
InputStream inputStream = FileHandle.class.getResourceAsStream(path); //charge json in "InputStream"
return inputStream;
}catch(Exception e) {
e.printStackTrace(); //tracer for json exceptions
}
return null;
}
public static String getJsonStringFromFile(String path) {
Scanner scanner;
InputStream in = inputStreamFromFile(path); //obtains the content of the .JSON and saves it in: "in" variable
scanner = new Scanner(in); //new scanner with inputStream "in" info
String json= scanner.useDelimiter("\\Z").next(); //reads .JSON and saves it in string "json"
scanner.close(); //close the scanner
return json; //return json String
}
public static boolean objectExists (JSONObject jsonObject, String key) { //verifies whether an object exist in the json
Object o;
try {
o=jsonObject.get(key);
}catch(Exception e) {
return false;
}
return o!=null;
}
public static JSONObject getJSONObjectFromFile(String path) { //creates a jsonObject from a path
return new JSONObject(getJsonStringFromFile(path));
}
So, after writing in JSON file, I cant do anything with it, because with this weird symbols, I got errors in my json: "extraneus input: (here are the symbols) expecting [STRING, NUMBER, TRUE, FALSE, {..."

writeUTF does not write standard unicode but prepends the output with two bytes of length information
If you use writeUTF intentionally, you have to use readUTF to read the data again. Otherwise I would suggest using an OutputStreamWriter.
writeUTF()
Writes two bytes of length information to the output stream, followed
by the modified UTF-8 representation of every character in the string
s. If s is null, a NullPointerException is thrown. Each character in
the string s is converted to a group of one, two, or three bytes,
depending on the value of the character.
** Edit to clarify OutputStreamWriter:
To use the OutputStreamWriter just replace the ObjectOutputStream with OutputStreamWriter and use write instead of writeUTF.
You might find this small tutorial helpfull: Java IO: OutputStreamWriter on jenkov.com

Related

I get a chinese character in my txt file when using BufferedWriter and FileWriter. How can I get my integer to write to "caseCountFile" correctly?

Here is the code:
public static void main(String[] args) {
try {
String url = "https://www.health.pa.gov/topics/disease/coronavirus/Pages/Cases.aspx";
Document doc = Jsoup.connect(url).get();
Elements info = doc.getElementsByTag("strong");
FileWriter fw = new FileWriter("data");
fw.write(info.toString());
fw.close();
String caseCount = Files.readAllLines(Paths.get("data")).get(2);
String caseCount1 = caseCount.replaceFirst("<strong>", "");
String caseCount2 = caseCount1.substring(0, caseCount1.length()-9);
String caseCount3 = caseCount2.replaceAll(",", "");
System.out.println(caseCount3);
int actualCaseCount = Integer.parseInt(caseCount3.toString());
System.out.println(actualCaseCount);
String oldCaseCount = Files.readAllLines(Paths.get("caseCountFile")).get(0);
int newOldCaseCount = Integer.valueOf(oldCaseCount.toString());
BufferedWriter bw = new BufferedWriter(new FileWriter("caseCountFile"));
bw.write(actualCaseCount);
bw.flush();
System.out.println(actualCaseCount - newOldCaseCount);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Is it something to do with how the data I scraped is encoded from the CDC website? The culprit variable is "actualCaseCount": When I print it to the console, prints correctly. When I write it to the txt file, it prints this: "毉"
I'm trying to write the number of total COVID cases in the US from the CDC page to a text file so I can track day to day changes in the data.
Yes, I'm new at this.
Thanks
It looks like you're writing the actual number to the file (which gets encoded as a number of bytes), instead of the String value of the number.
Try doing
bw.write(actualCaseCount.toString());
Or, since it's the same value as caseCount3 you could do this instead
bw.write(caseCount3);

Java : Writing CSV in String format to CSV in a file

A method returns a String in comma separated format. For example, the returned String can be like the one given below.
Tarantino,50,M,USA\n Carey Mulligan,27,F,UK\n Gong Li,45,F,China
I will need to get this String and write it into a CSV file. I'll have to insert a header and a footer for this file as well.
For example, when I open the file, the contents for the above data will be
Name,Age,Gender,Country
Tarantino,50,M,USA
Carey Mulligan,27,F,UK
Gong Li,45,F,China
How do we do that ? Are there any open source libraries to do this task ?
CSV format is not very well defined. You don't have to write headers for the file. Instead it is pretty SIMPLE format. Data values are separated using commas or semicolon or space etc.
You just have to write your own simple method that writes your string to a file on local computer using FileOutputStream or Writer in java.io package.
You can use this as a learning example.
I used BufferedReader because he will take care about line separators, but you can also use #split method, and write the resulting tokens.
import java.io.*;
public class Tests {
public static void main(String[] args) {
File file = new File("out.csv");
BufferedWriter out = null;
try {
out = new BufferedWriter(new FileWriter(file));
String string = "Tarantino,50,M,USA\n Carey Mulligan,27,F,UK\n Gong Li,45,F,China";
BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(string.getBytes())));
String line;
while ((line = reader.readLine()) != null) {
out.write(line.trim());
out.newLine();
}
}
catch (IOException e) {
// log something
e.printStackTrace();
}
finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
// ignored
}
}
}
}
}
This is pretty simple
String str = "Tarantino,50,M,USA\n Carey Mulligan,27,F,UK\n Gong Li,45,F,China";
PrintWriter pr = new PrintWriter(new FileWriter(new File("test.csv"), true));
String arr[] = str.split("\\n");
// splited the string by new line provided with the string
pr.println("Name,Age,Gender,Country");
// header written first and rest of data appended
for(String s : arr){
pr.println(s);
}
pr.close();
don't forget to close the stream in finally block and handle the exception

How do I convert List<String[]> values from UTF-8 to String?

I want to convert some greek text from UTF-8 to String, because they cannot be recognized by Java. Then, I want to populate them into a JTable. So I use List to help me out. Below I have the code snippet:
String[][] rowData;
List<String[]> myEntries;
//...
try {
this.fileReader = new FileReader("D:\\Book1.csv");
this.reader = new CSVReader(fileReader, ';');
myEntries = reader.readAll();
//here I want to convert every value from UTF-8 to String
convertFromUTF8(myEntries); //???
this.rowData = myEntries.toArray(new String[0][]);
} catch (FileNotFoundException ex) {
Logger.getLogger(VJTable.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(VJTable.class.getName()).log(Level.SEVERE, null, ex);
}
//...
I created a method
public String convertFromUTF8(List<String[]> s) {
String out = null;
try {
for(String stringValues : s){
out = new String(s.getBytes("ISO-8859-1"), "UTF-8");
}
} catch (java.io.UnsupportedEncodingException e) {
return null;
}
return out;
}
but I cannot continue, because there is no getBytes() method for List.
What should I do. Any idea would be very helpful. Thank you in advance.
The problem is your use of FileReader which only supports the "default" character set:
this.fileReader = new FileReader("D:\\Book1.csv");
The javadoc for FileReader is very clear on this:
The constructors of this class assume that the default character
encoding and the default byte-buffer size are appropriate. To specify
these values yourself, construct an InputStreamReader on a
FileInputStream.
The appropriate way to get a Reader with a character set specified is as follows:
this.fileStream = new FileInputStream("D:\\Book1.csv");
this.fileReader = new InputStreamReader(fileStream, "utf-8");
To decode UTF-8 bytes to Java String, you can do something like this (Taken from this)
Charset UTF8_CHARSET = Charset.forName("UTF-8");
String decodeUTF8(byte[] bytes) {
return new String(bytes, UTF8_CHARSET);
}
Once you've read the data into a String, you don't have control over encoding anymore. Java stores Strings as UTF-16 internally. If the CSV file you're reading from is written using UTF-8 encoding, you should read it as UTF-8 into the byte array. And then you again decode the byte array into a Java String using above method. Now once you have the complete String, you can probably think about splitting it to the list of Strings based on the delimiter or other parameters (I don't have clue about the data you've).

Unable to split json response?

This is my method
public String buildJsonData(String username , String message)
{
JsonObject jsonObject = Json.createObjectBuilder().add("Username",username+":"+message).build();
StringWriter stringWriter = new StringWriter();
try(JsonWriter jsonWriter = Json.createWriter(stringWriter))
{
jsonWriter.write(jsonObject);
}
catch(Exception e)
{
System.out.print("buildJsonData ="+e);
}
return stringWriter.toString();
}
If i input username as john and message as hello.I get output as
{"Username":"john:hello"}
But I want output without braces and doublequotes I want my output as
John:hello
I tried to split it using array[0] but didn't get the output.Is it possible in json to get my desired output(without braces and quotes).
On the sending end, you would put the Username and Message entities into a JSONObject and send the resulting string over the network.
On the receiving end, you would unmarshal the JSON to extract the entities. You can then format them however you like.
Please read about JSON encoding here.
This is a simple example:
private String getResponse(){
JSONObject json = new JSONObject();
try {
json.put("Username", "John");
json.put("Message", "Hellow");
} catch (JSONException e) {
e.printStackTrace();
}
return json.toString();
}
private void receiver(){
try {
JSONObject response = new JSONObject(getResponse());
String username = response.getString("Username");
String message = response.getString("Message");
System.out.println(String.format("%s : %s", username,message));
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Your structure is not really JSON.
A json structure would be like
{
Username : "John",
Message : "Hello"
}
Anf if your want to really use JSON, there is not way to remove braces and quotes. This IS Json.
If you want to output only the part you quoted, store the json value in a variable
String myoutput = stringWriter.toString();
And then remove the parts you don't want with replace() or a regexp
Braces are part of the JSON notation - they indicate an object. If you remove them, then it's not JSON any more. Same goes for double quotes.You are creating your JSON object as:
Json.createObjectBuilder().add("Username",username+":"+message)
This creates an object with property named Username and value john:hello. Again, this is the JSON notation. It's not intended to be read directly, but to facilitate data transfer between applications (on the same or different devices).
If all you want to create is john:message, then instead of creating a JSON object, you should simply do:
String result = username + ":" + message;
return result;

Parse text from webpage in Java (not html)

I am using this code to download a string from a website:
static public String getLast() throws IOException {
String result = "";
URL url = new URL("https://www.bitstamp.net/api/ticker/");
BufferedReader in = new BufferedReader(new InputStreamReader(
url.openStream()));
String str;
while ((str = in.readLine()) != null) {
result += str;
}
in.close();
return result;
}
When I print the result of this method, this is what I get:
{"high": "349.90", "last": "335.23", "timestamp": "1384198415", "bid": "335.00", "volume": "33743.67611671", "low": "300.28", "ask": "335.23"}
That's exactly what is shown when you open the URL. This works fine for me, but if there is a more efficient way to do this please let me know.
What I need to extract is 335.23. This number is constantly changing, but the words such as "high", "last", "timestamp", etc always stay the same. I need to extract the 335.23 as a double. Is this possible?
Edit:
SOLVED
String url = "https://www.bitstamp.net/api/ticker/";
try {
JsonFactory factory = new JsonFactory();
JsonParser jParser = factory.createParser(new URL(url));
while (jParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jParser.getCurrentName();
if ("last".equals(fieldname)) {
jParser.nextToken();
System.out.println(jParser.getText());
break;
}
}
jParser.close();
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JarException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
This is JSON. Use a good parser like Jackson. There are also good Tutorials available.
The response is a json. Use a java JSON Parser and get value for "high" element.
One of the java json parsers is available on (http://www.json.org/java/index.html)
JSONObject obj = new JSONObject(" .... ");
String pageName = obj.getString("high");
The data String that you have received is known as JSON encoding. JSON (JavaScript Object Notation) is a lightweight data-interchange format. Use a fine grain simple json encoder and decoder to encode and decode data.

Categories