I used this code to verify a digital sign of a file, the constructor prints the context of the file but I wanted to know how to save the print as a variable , since a constructor uses only to "build" objects, this is the code:
public class VerifyMessage {
private List<byte[]> list;
#SuppressWarnings("unchecked")
// The constructor of VerifyMessage class retrieves the byte arrays from the File and prints the message only if the signature is verified.
public VerifyMessage(String filename, String keyFile) throws Exception {
ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename));
this.list = (List<byte[]>) in.readObject();
in.close();
System.out.println(verifySignature(list.get(0), list.get(1), keyFile) ? "VERIFIED MESSAGE" + "\n----------------\n" + new String(list.get(0)) : "Could not verify the signature.");
}
How can I "save" the System.out.println as a global member String variable outside of the constructor?
thanks ahead
Your class already contains a list field.
Similar to that, you declare a string field- and then you simply assign the value you are currently printing to that field.
public class VerifyMessage {
private List<byte[]> list;
Object variable = null;
public VerifyMessage(String filename, String keyFile) throws Exception {
ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename));
this.list = (List<byte[]>) in.readObject();
in.close();
this.variable = this.verifySignature(list.get(0), list.get(1), keyFile);
}
private Object verifySignature(byte[] bs, byte[] bs2, String keyFile) {
//
return null;
}
}
Related
I need to serialize an Object in java. Currently I'm doing it by using this code, which does:
ObjectOutputStream.writeObject(obj);
Base64 encode the obj
And reversing the process.
It works fine for primitive types inside the class, such as long and int.
However, all String objects inside that object become null. I'd need them to be included as well. Is there any way to do that?
Edit: code I'm using
// Modified from source: https://stackoverflow.com/questions/134492/how-to-serialize-an-object-into-a-string
public static Object FromString( String s )
{
Object o = null;
try {
byte[] data = Base64.getDecoder().decode(s);
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(data));
o = ois.readObject();
ois.close();
}
catch(Exception e)
{
System.out.println(e);
}
return o;
}
// Modified from source: https://stackoverflow.com/questions/134492/how-to-serialize-an-object-into-a-string
public static String ToString( Serializable o )
{
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
}
catch(Exception e)
{
System.out.println(e);
}
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
EDIT: Pojo
public class SignedTimestamp implements Serializable {
private Long obj;
private byte[] signature;
private String signatureAsAString;
}
Output on the other application (receiving the data and deserializing):
obj = 1494609033621;
signature = null;
signatureAsAString = null;
I have just tested your code, and it's working okay.
I've created a source named SignedTimeStamp.java:
import java.io.*;
public class SignedTimestamp implements Serializable {
private Long obj;
private byte[] signature;
private String signatureAsAString;
public SignedTimestamp(Long obj, byte[] signature, String signatureAsAString) {
this.obj = obj;
this.signature = signature;
this.signatureAsAString = signatureAsAString;
}
public Long getObj() {
return this.obj;
}
public byte[] getSignature() {
return this.signature;
}
public String getSignatureAsAString() {
return this.signatureAsAString;
}
}
And declared another called Serializables.java, containing your code:
import java.io.;
import java.util.;
public class Serializables {
public static Object FromString(String s) {
Object o = null;
try {
byte[] data = Base64.getDecoder().decode(s);
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(data));
o = ois.readObject();
ois.close();
}
catch(Exception e)
{
System.out.println(e);
}
return o;
}
// Modified from source: http://stackoverflow.com/questions/134492/how-to-serialize-an-object-into-a-string
public static String ToString( Serializable o ) {
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
}
catch(Exception e)
{
System.out.println(e);
}
return Base64.getEncoder().encodeToString(baos.toByteArray());
}
}
Then, I created one main class in Serialize.java:
public class Serialize {
public static void main(String[] args) throws Exception {
SignedTimestamp o = new SignedTimestamp(100L, new byte[]{ (byte) 128 }, "Hello, world!");
System.out.println(Serializables.ToString(o));
}
}
Which returned me this result:
sh-4.3$ java Serialize
rO0ABXNyAA9TaWduZWRUaW1lc3RhbXCGTHiJ+JenzgIAA0wAA29ianQAEExqYXZhL2xhbmcvTG9uZztbAAlzaWduYXR1cmV0AAJbQkwAEnNpZ25hdHVyZUFzQVN0cmluZ3QAEkxqYXZhL2xhbmcvU3RyaW5nO3hwc3IADmphdmEubGFuZy
5Mb25nO4vkkMyPI98CAAFKAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAAAAABkdXIAAltCrPMX+AYIVOACAAB4cAAAAAGAdAANSGVsbG8sIHdvcmxkIQ==
sh-4.3$
Then, I created another main class in Deserialize.java:
public class Deserialize {
public static void main(String[] args) throws Exception {
String serialized =
"rO0ABXNyAA9TaWduZWRUaW1lc3RhbXCGTHiJ+JenzgIAA0wAA29ianQAEExqYXZhL2xhbmcvTG9uZztbAAlzaWduYXR1cmV0AAJbQkwAEnNpZ25hdHVyZUFzQVN0cmluZ3QAEkxqYXZhL2xhbmcvU3RyaW5nO3hwc3IADmphdmEubGFuZy" +
"5Mb25nO4vkkMyPI98CAAFKAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAAAAABkdXIAAltCrPMX+AYIVOACAAB4cAAAAAGAdAANSGVsbG8sIHdvcmxkIQ==";
SignedTimestamp o = (SignedTimestamp) Serializables.FromString(serialized);
System.out.println(o.getObj());
System.out.println(o.getSignature());
System.out.println(o.getSignatureAsAString());
}
}
And it returns this:
sh-4.3$ java Deserialize
100
[B#6bc7c054
Hello, world!
sh-4.3$
So, all in all, the code seems to be working perfectly.
How did you test your code? Perhaps the mistake is there.
I dont see any problem in that code. Please post your code so that we will dig further.
tried from my end:
Encoded serialized version
rO0ABXNyAAhFbXBsb3llZTLR4JLRYAw9AgAESQAGbnVtYmVyTAAHYWRkcmVzc3QAEkxqYXZhL2xhbmcvU3RyaW5nO0wADWFkZHJlc3NPYmplY3R0AAlMQWRkcmVzcztMAARuYW1lcQB+AAF4cAAAAGV0ABlQaG9ra2EgS3VhbiwgQW1iZWh0YSBQZWVyc3IAB0FkZHJlc3MkcEtPHXHTqQIAAUwACGFkZHJMaW5lcQB+AAF4cHEAfgAEdAAJUmV5YW4gQWxp
Reconstituted object
Employee [name=Reyan Ali, address=Phokka Kuan, Ambehta Peer, number=101, addressObject=Address [addrLine=Phokka Kuan, Ambehta Peer]]
I have written a java program that needs to save a list of an Object I created called User. This is my code for saving and loading the list:
/**
* Save list to file
* #param saveList list to be saved
*/
public void saveUsers(List<User> saveList){
try{
FileOutputStream fileOut = new FileOutputStream("data/userlist.ser", true);
OutputStream out = new BufferedOutputStream(fileOut);
ObjectOutput output = new ObjectOutputStream(out);
output.writeObject(saveList);;
out.close();
fileOut.close();
output.close();
for(User u : saveList){
System.out.println(u.getUsername());
}
System.out.println("List written to file");
}catch(IOException e){
e.printStackTrace();
}
}
/**
*
* #return list of all users in system.
*/
#SuppressWarnings({ "resource", "unchecked" })
public static List<User> loadUsers(){
try{
InputStream saveFile = new FileInputStream("data/userlist.ser");
InputStream buffer = new BufferedInputStream(saveFile);
ObjectInput input= new ObjectInputStream(buffer);
LinkedList<User> loadList = (LinkedList<User>) input.readObject();
System.out.println(loadList.size());
for(User u : loadList){
u.reload();
System.out.println(u.getUsername());
}
return loadList;
}catch(Exception e){
e.printStackTrace();
}
List<User> l = new LinkedList<User>();
return l;
}
And my code seems to work for save because the output each time it is called shows all the users being added to the list, however on the load it only loads the first User. This is my user class:
public class User implements Serializable{
/**
* Variables
*/
private transient StringProperty usernameProperty;
private String username;
private List<Album> albums = new LinkedList<Album>();
private List<Photo> photos = new LinkedList<Photo>();;
private List<Tag> tags = new LinkedList<Tag>();;
private static final long serialVersionUID = 1738L;
/**
* public constructor to create a user
* #param username
*/
public User(String username){
this.username = username;
this.usernameProperty = new SimpleStringProperty(username);
}
And all of my other classes are implementing the Serializable as well. Is there any reason the list is being saved to the file but not loading fully?
I figured out the answer, apparently every time I was calling the save class, I was not overwritting the file but appending to it, so I was only reading the first array list being stored, pretty simple fix I just added the lines
File file = new File("data/userlist.ser");
file.delete();
to the beginning of my saveUsers function to clear the file, now it works perfectly.
Change LinkedList loadList = (LinkedList) input.readObject(); to ArrayList. Edit the file userlist.ser delete the contents or create a new file and use it in your code. It works fine for me.
Finding the error in your code is for me more complex than testing my own solution, so I have made a quick model for you, using a the same classes you use, but using a custom class (car) for this...
the Code:
public static void main(String[] args) throws Exception {
final Car c0 = new Car("bmw", 1990);
final Car c1 = new Car("VW", 2000);
final Car c2 = new Car("Audi", 2010);
final Car c3 = new Car("Mini", 2015);
final LinkedList<Car> lisCar = new LinkedList<Car>();
lisCar.add(c0);
lisCar.add(c1);
lisCar.add(c2);
lisCar.add(c3);
serialThis(lisCar);
deserializeFileToList();
}
Serialize to file:
private static void serialThis(LinkedList<Car> lisCar) throws Exception {
final FileOutputStream fos = new FileOutputStream("serialized.txt");
final ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(lisCar);
oos.close();
}
Deserialize from file:
private static void deserializeFileToList() throws Exception {
final FileInputStream fis = new FileInputStream("serialized.txt");
final ObjectInputStream ois = new ObjectInputStream(fis);
final LinkedList<Car> ds = (LinkedList<Car>) ois.readObject();
ois.close();
System.out.println(ds);
}
The Car class:
private static final long serialVersionUID = -427928246789764110L;
#Override
public String toString() {
return "Car [year=" + year + ", type=" + type + "]";
}
private final int year;
private final String type;
public Car(String type, int year) {
this.type = type;
this.year = year;
}
I have succeeded in writing and reading a string to a file on my android app's internal storage, but I want to write an object and it's not working. I've read Oracle's documentation on the matter, which says for object fields to be transmitted over the stream the object needs to implement serializable, or something. I added imports serializable and implements serializable to the cat class but it threw an error. Without it "oos.writeObject(myCat);" causes an error too. I'm very confused.
The below code exists in a java activity class tied to a layout.xml. The user presses a button and the object is saved or loaded. As stated writing and reading a string seems to work fine, but objects less so.
private void writeFile()
{
try
{
String myFile = "myFile";
cat myCat = new cat("Harry", "blue", 11);
FileOutputStream fos = openFileOutput(myFile,MODE_WORLD_READABLE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(myCat);
oos.close();
fos.close();
Toast.makeText(getBaseContext(),"object saved",Toast.LENGTH_SHORT).show();
}
catch (Exception e)
{
e.printStackTrace();
}
}
And
private void readFile()
{
try
{
String myFile = "myFile";
FileInputStream fis = openFileInput(myFile);
ObjectInputStream ois = new ObjectInputStream(fis);
cat yourCat = (cat) ois.readObject();
ois.close();
fis.close();
String output = yourCat.name + " the " + yourCat.colour + " cat";
Toast.makeText(getBaseContext(),output,Toast.LENGTH_SHORT).show();
}
catch (Exception e)
{
}
}
The cat object
public class cat
{
public String name = "";
public String colour = "black";
public int age = 0;
public cat(String pName, String pColour, int pAge)
{
name = pName;
colour = pColour;
age = pAge;
}
}
Adding "implements Serializable" to the cat class works. I'm not sure why it didn't in the first place. Sorry for the fuss.
Try using:
MODE_PRIVATE
In the openFileOutput() method.
I have a function that returns map value (String) as a generic Object. How do I convert it back to string. I tried toString() but all i get is end[Ljava.lang.String;#ff2413
public Object getParameterValue(String key)
{
Iterator iterator=params.entrySet().iterator();
while(iterator.hasNext())
{
Map.Entry me=(Map.Entry)iterator.next();
String[] arr=(String[])me.getValue();
log.info(me.getKey().toString()+"="+arr[0]);
}
if(params.containsKey(key))
{
log.info(key+"="+params.get(key));
return params.get(key);
}
return null;
}
Receiving end
String temp=data.getParameterValue("request").toString();
log.info("end"+temp);
log.info(me.getKey().toString()+"="+arr[0]); give me an output
email=x#as.com
request=login
projectid=as
I'm afraid your map contains something other than String objects. If you call toString() on a String object, you obtain the string itself.
What you get [Ljava.lang.String indicates you might have a String array.
Might not be so related to the issue above. However if you are looking for a way to serialize Java object as string, this could come in hand
package pt.iol.security;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import org.apache.commons.codec.binary.Base64;
public class ObjectUtil {
static final Base64 base64 = new Base64();
public static String serializeObjectToString(Object object) throws IOException {
try (
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(arrayOutputStream);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(gzipOutputStream);) {
objectOutputStream.writeObject(object);
objectOutputStream.flush();
return new String(base64.encode(arrayOutputStream.toByteArray()));
}
}
public static Object deserializeObjectFromString(String objectString) throws IOException, ClassNotFoundException {
try (
ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(base64.decode(objectString));
GZIPInputStream gzipInputStream = new GZIPInputStream(arrayInputStream);
ObjectInputStream objectInputStream = new ObjectInputStream(gzipInputStream)) {
return objectInputStream.readObject();
}
}
}
maybe you benefit from converting it to JSON string
String jsonString = new com.google.gson.Gson().toJson(myObject);
in my case, I wanted to add an object to the response headers but you cant add objects to the headers,
so to solve this I convert my object to JSON string and in the client side I will return that string to JSON again
Looking at the output, it seems that your "temp" is a String array. You need to loop across the array to display each value.
The result is not a String but a String[]. That's why you get this unsuspected printout.
[Ljava.lang.String is a signature of an array of String:
System.out.println(new String[]{});
The question how do I convert an object to a String, despite the several answers you see here, and despite the existence of the Object.toString method, is unanswerable, or has infinitely many answers. Because what is being asked for is some kind of text representation or description of the object, and there are infinitely many possible representations. Each representation encodes a particular object instance using a special purpose language (probably a very limited language) or format that is expressive enough to encode all possible object instances.
Before code can be written to convert an object to a String, you must decide on the language/format to be used.
To convert serialize object to String and String to Object
stringToBean(beanToString(new LoginMdp()), LoginMdp.class);
public static String beanToString(Object object) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
StringWriter stringEmp = new StringWriter();
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
objectMapper.writeValue(stringEmp, object);
return stringEmp.toString();
}
public static <T> T stringToBean(String content, Class<T> valueType) throws IOException {
return new ObjectMapper().readValue(content, valueType);
}
Solution 1: cast
String temp=(String)data.getParameterValue("request");
Solution 2: use typed map:
Map<String, String> param;
So you change Change the return type of your function
public String getParameterValue(String key)
{
if(params.containsKey(key))
{
return params.get(key);
}
return null;
}
and then no need for cast or toString
String temp=data.getParameterValue("request");
toString() is a debug info string. The default implementation returns the class name and the system identity hash. Collections return all elements but arrays not.
Also be aware of NullPointerException creating the log!
In this case a Arrays.toString() may help:
Object temp = data.getParameterValue("request");
String log = temp == null ? "null" : (temp.getClass().isArray() ? Arrays.toString((Object[])temp) : temp.toString());
log.info("end " + temp);
You can also use Arrays.asList():
Object temp = data.getParameterValue("request");
Object log = temp == null ? null : (temp.getClass().isArray() ? Arrays.asList((Object[])temp) : temp);
log.info("end " + temp);
This may result in a ClassCastException for primitive arrays (int[], ...).
/** * This toString-Method works for every Class, where you want to display all the fields and its values */ public String toString() {
StringBuffer sb = new StringBuffer();
Field[] fields = getClass().getDeclaredFields(); //Get all fields incl. private ones
for (Field field : fields){
try {
field.setAccessible(true);
String key=field.getName();
String value;
try{
value = (String) field.get(this);
} catch (ClassCastException e){
value="";
}
sb.append(key).append(": ").append(value).append("\n");
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return sb.toString(); }
You can create toString() method to convert object to string.
int bid;
String bname;
double bprice;
Book(String str)
{
String[] s1 = str.split("-");
bid = Integer.parseInt(s1[0]);
bname = s1[1];
bprice = Double.parseDouble(s1[2]);
}
public String toString()
{
return bid+"-"+bname+"-"+bprice;
}
public static void main(String[] s)
{
Book b1 = new Book("12-JAVA-200.50");
System.out.println(b1);
}
I am reading Thinking in Java 4th Edition.
There described a strange workaround for serialization of transient fields:
import java.io.*;
public class SerializationTest implements Serializable {
private String firstData;
//transient field, shouldn't be serialized.
transient private String secondData;
public SerializationTest(String firstData, String test2) {
this.firstData = firstData;
this.secondData = test2;
}
/**
* Private method, same signature as in Serializable interface
*
* #param stream
* #throws IOException
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(secondData);
}
/**
* Private method, same signature as in Serializable interface
*
* #param stream
* #throws IOException
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
secondData = (String) stream.readObject();
}
#Override
public String toString() {
return "SerializationTest{" +
"firstData='" + firstData + '\'' +
", secondData='" + secondData + '\'' +
'}';
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream("object.out");
oos = new ObjectOutputStream(fos);
SerializationTest sTest = new SerializationTest("First Data", "Second data");
oos.writeObject(sTest);
} finally {
oos.close();
fos.close();
}
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream("object.out");
ois = new ObjectInputStream(fis);
SerializationTest sTest = (SerializationTest) ois.readObject();
System.out.println(sTest);
} finally {
ois.close();
fis.close();
}
//Output:
//SerializationTest{firstData='First Data', secondData='Second data'}
}
}
As you can see, there are implemented private methods writeObject and readObject.
The questions are:
For what ObjectOutputStream and ObjectInputStream are using Reflection for accessing private methods ?
How many back doors like this are included in the Java ?
Backdoor? It's always been in the spec. It is the only way to implement non-default serialization of an object.
Non-default serialization puts you in the serialization driver's seat. You can write whatever to the output stream and as long as you can read it back and construct your object on the other end of the stream, you'll be ok.
The fact that this person decided to serialize transient fields is just not the issue, the point is that you can do whatever you want if you are implementing your own serialization scheme.
Erm, it isn't a "backdoor" ... you implemented a custom serialization that output the transient fields to the output stream after calling the default serialization which ignored them.
The Serializable interface is marker interface. So its like a tag to explain the java compiler. There are other marker interfaces like Clonable, etc. See here for more.
However now a days #annotations are used more.