È difficile rispondere con le informazioni fornite. Ad esempio, dici di "stringificare" i dati, ma non stai dicendo quale metodo stai usando. C'è una libreria che stai usando? La stringa JSON, XML o altri dati strutturati?
Suppongo che tu stia utilizzando qualche tipo di dati strutturati (per semplicità, diciamo JSON che usa GSON o simili).
Quindi al momento della scrittura, creerai e scrivi una stringa
public void writeToFile(String filname, Object myObject) {
String serialized = new Gson().toJson(myObject);
try(FileOutputStreamoutputStream output =
openFileOutput(filename, Context.MODE_PRIVATE)
) {
output.write(s.getBytes());
} catch (Exception e) {
Log.e("MyApplication",
"Unable to write " + serialized + " to file " + filename + " with exception",
e
);
}
}
E al momento della lettura, ti basterà leggere i dati indietro. Bene, è piuttosto facile
public <T> T read(String filename, Class<T> clazz) {
String serialized = new Gson().toJson(myObject);
try (
BufferedReader reader = new BufferedReader(
new InputStreamReader(
openFileInput(filename, Context.MODE_PRIVATE)
)
)
) {
StringBuilder json = new StringBuilder();
String line;
while((line = reader.nextLine()) != null) {
json.append(line);
}
return new Gson().fromJson(json.toString, clazz);
} catch (Exception e) {
Log.e(
"MyApplication",
"Unable to read " + filename + " to class " + clazz.simpleName() + " with exception",
e
);
return null;
}
}
Ma aspetta, hai detto che hai cambiato il nome di un campo. Bene, la soluzione più semplice è semplicemente non aver cambiato il nome di detto campo. Ma questo è il mondo reale, ci sono requisiti aziendali, sviluppatori pomposi che sanno più dei loro predecessori, o qualsiasi altra cosa. Hai ereditato il codice. Non ho intenzione di incolparti per questo.
Quindi, la prossima soluzione più semplice è quella di mantenere le versioni precedenti delle tue classi. Ad esempio, puoi avvolgere la tua funzione di lettura con
public <T> T readFromFile(String filename, Transformer<T> optimusPrime) {
for(Class clazz : optimusPrime.getSupportedClasses()) {
//TODO optimize this (haha, like that'll get prioritized)
Object o = read(filename, supportedIterator.next())
if(o != null) {
return optimusPrime.transform(o)
}
}
return null;
}
Dove la classe del trasformatore ha una raccolta di tutte le possibili classi che potrebbero essere mai state memorizzate nel file (si spera in ordine dal più o meno probabile), e un metodo generale per tradurre tra loro. Probabilmente sarebbe simile a questo
public class OptimusPrime implements Transformer<Autobot> {
private final Map<Class, TransformMethod> transformations;
public OptimusPrime() {
transformations = new TreeMap<>;
transformations.put(Megatron.class, new MegatronTransform());
transformations.put(Starscream.class, new StarscreamTransform());
transformations.put(Shockwave.class, new ShockwaveTransform());
//Shhhh
}
@Override
public Collection<Class> getSupportedClasses() {
return transformations.keySet();
}
@Override
public Autobot transform(Object o) {
TransformMethod<Autobot> transformation = transformations.get(o.getClass());
return (transformation == null) ? null : transformation.transform(o);
}
}
E
public class MegatronTransform implements TransformMethod<Autobot> {
@Override
public Megatron transform(Object o){
return (Megatron) o;
}
}
Quindi, è fattibile, ma il tuo codice base si gonfierà e non sarai mai in grado di sbarazzarti di tutte quelle vecchie classi nel tuo codice a meno che tu non fornisca all'utente qualche errore e metodo di recupero, o tu? re sicuro al 100% che nessun utente abbia il tipo di dati legacy memorizzato sul proprio dispositivo.
Quale sarebbe l'opzione più semplice (più costosa) sarebbe quella di archiviare i dati all'interno di un'API con versione da qualche parte nel "cloud". In questo modo puoi avere il controllo sui dati e sul meccanismo di archiviazione.