View Full Version : [Java] Problema... non so programmare


Ing.StefanoM.
08-06-2010, 20:46
Vi illustro il mio problema in modo sintetico.

Ho una serie di dati dislocati su un certo quantitativo di file.
I dati sono scritti in un ordine particolare, tipo:
file A parte 1, file A parte 2, file B parte 1 -> file AAA
file A parte 3, file B parte 2, file B parte 3 -> file BBB
... ovviamente è un esempio.

Ho già un programmino in java che legge i file AAA e BBB e rimette tutto in ordine corretto, in modo che l'output sia "leggibile". Gentilmente è stato programmato da un amico, no-profit. es.:
file AAA + BBB -> file AAA riordinato, file BBB riordinato

Personalmente ho creato tutti quelli che sono gli algoritmi logici, del programma.

Ora il mio compare è via per lavoro e io ho bisogno della procedura inversa; esempio:
file AAA riordinato + file BBB riordinato -> file AAA, file BBB.

Avrei già buttato giù una procedura logica per la procedura inversa... vorrei sapere se qualcuno, per caso, magari come esercizio, potrebbe buttarmi giù il programma, sotto mie indicazioni. Ve lo chiedo direttamente, perchè se no dovrei chiedere ad ogni funzione che mi serve scrivere, un aiuto.

p.s: non focalizzatevi su quegli esempi semplicistici :) la cosa è più complessa di così.

nuovoUtente86
08-06-2010, 20:52
Inizia a scrivere qualcosa, poi saramo tutti felici di autarti. Ma nessuno si metterà a scolgere il lavoro per te.

ErFranz
08-06-2010, 22:41
Guarda, purtroppo per te non troverai nessuno che ti svolga l' intero programma. A parte il fatto che è proprio scritto nel regolamento, ma proprio per una questione di rispetto nei riguardi degli altri utenti.
Ora a parte questo, comincia magari a descriverci la tua logica, e poi sarai sempre tu a scrivere codice. Se non sei in grado a priorio aimè ti consiglio di pagare qualcuno se lo trovi, oppure di perdere parecchio tempo per farlo...Mi spiace...ciao ciao

Ing.StefanoM.
08-06-2010, 23:51
Allora.... posso postare direttamente il programma che è stato compilato per leggere dai dati. Allego java, con tanto di commenti.

Le due funzioni usate per leggere e per saltare i dati sono state: read() e skip().

Ora, come potete vedere non è sia esattamente così semplice come nell'esempio. Io avrei bisogno in sostanza di "invertirlo". Cioè... devo leggere dal file "extracted.dat" e quindi scrivere le porzioni corrette di dati, nelle esatte posizioni da cui sono state lette (è ovvio che mi serve per effettuare modifiche su un file leggibile e poi reinserlo nel database).

Scrivo di seguito la "logica" per l'inverso del programma.
_______________________________________
/* 1th block */
currentfile extracted.dat
read: "339968 Byte" -> fillbuffer
currentfile Data0012
jumpNhex: "896A000"
write buffer
typefile = 1
1th-jump = 1
currentfile extracted.dat

/* Xnd block */
{While (read: "835584 Byte" != -1) /* fino a quando riesce a leggere 835.584 Byte di fila */
case: typefile = 1: currentfile Data0012;
if (1th-jump = 1): jumpNhex: "1000" & 1th-jump = 0
typefile = 2: open Data0013;
if (1th-jump = 1): jumpNhex: "2000" & 1th-jump = 0
typefile = 3: open Data0014;
if (1th-jump = 1): jumpNhex: "2000" & 1th-jump = 0
write buffer
jumpNhex: "1000"
if (jumpNhex = -1): typefile ++ & 1th-jump = 1 /* quando "salta" fuori dal file */
currentfile extracted.dat}

/* last block */
read: "604160 Byte"
currentfile Data0012
jumpNhex: "2000"
write buffer

/* Chiudi */
close all
_____________________________________________

Se ci sono dei dubbi vi consiglio di leggere il programma che "estrae" prima di leggere questa logica.

Vorrei avere qualche sorta di aiuto per programmare questa logica, che non è niente di impossibile.

Ciao.

PGI-Bis
09-06-2010, 05:18
A caval donato non si guarda in bocca, ergo soprassediamo sull'allegato (nel quale ci sono la bellezza di 6 bug).

Facciamone un esercizio di analisi volante, magari ci si diverte.

Risalendo dalla logica al fenomeno che si vuole rappresentare, io ci vedo sei "pezzi":

HeaderParser, BodyParser, FooterParser, Data0012, Data0013 e Data0014.

Ognuno di questi fa qualcosa e direi che tutti insieme portano avanti la carretta.

Che fa il primo? Piglia una sorgente dati, ne ricava un certo numero di byte e poi non ho ben capito ma direi che li passa a Data0012. E' giusto?

HeaderParser
+data una certa "sorgente dati"
-piglia i primi 339968 byte da quella sorgente
-mettili in Data0012, partendo da 144089088

Se è giusto, abbiamo un bel po' di altre cose interessanti da dire. SorgenteDati potrebbe essere una cosa come questa:

BinaryDataInput
+get(int start, int length): ByteBuffer

e Data0012 potrebbe essere una destinazione:

BinaryDataOutput
+put(int start, ByteBuffer data)

Devo però chiedere una conferma circa questa interpretazione perchè taglia un tot di cose dalla logica del primo blocco.

Facciamo finta che sia giusto. Lasciamo da parte BodyParser che è un po' misterioso. FooterParser.

Somiglia tanto a HeaderParser ma gli manca un pezzettino.

FooterParser
+con una certa sorgente dati
-leggi 604160 byte partendo da X
-mettili in Data0012 partendo da 8192

HeaderParser inizia da 0 e FooterParser? Diciamo che è parametrico anche in X (oltre che nella sorgente dati e in Data0012).

Anche qui fingiamo che vada bene.

BodyParser. Anche lui ha una sorgente dati ma la sua è più "intelligente". Sa vendersi a blocchi.

BodyParser
+con SpecialDataSource
-per ogni blocco di SpecialDataSource
...

E qui il mistero si infittisce. In questo "per ogni blocco" capita qualcosa. Io intravedo tre eventi, ognuno dei quali è gestito da un operatore diverso.

Quando capita che typefile sia 1, qualcuno scrive qualcosa su Data0012.
Quando capita che typefile sia 2, qualcuno scrive qualcosa su Data0013.
Quando capita che typefile sia 3, qualcuno scrive qualcosa su Data0014.

Diciamo che questi scrittori sono dei:

DataWriter(a chi)
+write(cosa, partendo da dove)

Sul chi siamo d'accordo. Cosa direi che sia il blocco del "per ogni blocco". E' il partendo da dove che mi perplime.

La perplessità mi sorge perchè se interpreto correttamente la logica, quel partendo da dove o è periodico, il che significa che prima o poi si finisce per scrivere sullo stesso pezzo di file e quindi il numero di blocchi da leggere è tutt'altro che indefinito e quindi non ci va il while, o è cumulativo, ma non vedo dove si accumuli.

Risolto questo dubbio, e sempre che la mia interpretazione del fenomeno da cui discende quella logica sia giusta, il programma è praticamente già scritto.

Ing.StefanoM.
10-06-2010, 00:33
Si, diciamo che la tua interpretazione è abbastanza corretta e direi anche intelligente.

Vado però a sviscerare meglio il programma "logico" da me postato, visto che qualcuno se n'è interessato.

/* 1th block */
currentfile extracted.dat
read: "339968 Byte" -> fillbuffer
currentfile Data0012
jumpNhex: "896A000"
write buffer
typefile = 1
1th-jump = 1
currentfile extracted.dat

Questo pezzo serve per leggere il primo blocco di dati dal cosiddetto file "extracted.dat" che rimane sempre il file sorgente da cui leggere. Il primo blocco di dati è lungo "339968 Byte". Dopo che è stato letto va inserito nel file "Data0012", però partendo dall'hex "896A000". Poi vado ad impostare due variabili, che mi servono per il ciclo di N blocchi successivo.

Come linea guida sappiate che: leggo dal file sorgente in modo continuo, ma scrivo nei vari file data00XX in modo discontinuo. Non solo perchè cambio file su cui scrivo, ma anche perchè quando scrivo su un file solo, lo faccio a blocchi di "835584 Byte", intervallando ad ogni scrittura un certo numero di byte.

/* Xnd block */
{While (read: "835584 Byte" != -1) /* fino a quando riesce a leggere 835.584 Byte di fila */
case: typefile = 1: currentfile Data0012;
if (1th-jump = 1): jumpNhex: "1000" & 1th-jump = 0
typefile = 2: open Data0013;
if (1th-jump = 1): jumpNhex: "2000" & 1th-jump = 0
typefile = 3: open Data0014;
if (1th-jump = 1): jumpNhex: "2000" & 1th-jump = 0
write buffer
jumpNhex: "1000"
if (jumpNhex = -1): typefile ++ & 1th-jump = 1 /* quando "salta" fuori dal file */
currentfile extracted.dat}

Ora... questo è il cuore del programma. E lo vado a spiegare.
Il ciclo WHILE mi serve appunto per entrare in ciclo. E appena parte mi va a leggere subito i miei buoni "835584 Byte" (ovviamente dal file sorgente, ma ovviamente non parte mica dall'inizio; parte dall primo byte non letto precedentemente). Non è esattamente esplicitato nella logica, ma se si va a leggere il programma precedente, si capisce che la READ() sa fin dove è arrivata l'ultima volta che ha letto e quindi se interpellata di nuovo, parte a leggere da dove era arrivata prima.

Ok, allora assodato che sto leggendo altri "835584 Byte". DOPO aver letto i dati il mio bel WHILE mi confronta la READ() col vaole -1. Questo serve perchè la READ() quando non riesce a leggere "835584 Byte" di fila, restituisce -1. E quindi serve come condizione di fine while.

Ok, ci siamo... siamo dentro il WHILE.
Parte la casistica. Se "typefile = 1" e "1th-jump = 1" (e all'inizio lo sono, li ho impostati io :) ), allora bisogna fare delle cose. Prima cosa da fare: impostare come file corrente di scrittura il file "Data0012". Seconda cosa: bisogna saltare i primi "hex 1000" e impostare "1th-jump = 0". Questo serve perchè devo iniziare a scrivere in punti diversi dei file "data00XX" e in particolar modo, la prima volta che salto dei bytes, devo farlo in modo particolare. Si noti che successivamente il salto di bytes è sempre costante.

Ok ci siamo... arrivo nel punto in cui volevo di "Data0012". Esco dalla casistica... e trovo un bel "writebuffer". Quindi il risultato è che scrivo il buffer che precedentemente avevo riempito con la lettura.

Cosa è successo ? Alla fine ho semplicemente letto un tot di bytes dalla sorgente, mi sono posizionato ad un certo livello dei file su cui volevo scrivere, e ho scritto.

Dopo la scrittura mi posiziono, sempre nel file "data0012" in avanti di "hex1000". Effettua un altro famoso "salto" in avanti.

Ottimo, entro nel ciclo IF (che sta nel ciclo while). Ora che succede ?
Se "jumpNhex = -1", che avviene solo se quando mi posiziono ad un certo livello di "Data00XX" ed esco fuori dal file; allora non faccio altro che impostare "typefile ++" e "1th-jump = 1". Ovviamente ciò non accade fino a che non "salto" appunto fuori dal file "data0012". Quindi dopo aver effettuato un "salto legale" ed essermi posizionato in un nuovo punto di "data0012", proseguo.

Reimposto come "current file" il file sorgente. Altrimenti quando riparte il ciclo WHILE, leggerà dalla sorgente sbagliata (nota: probabilmente a livello di programmazione non servirà continuare a reimpostare il file "corrente").

Ovviamente riparte il WHILE. Legge, confronta ed entra nella casistica. Reimposta il file corrente come "Data0012" e continua. L'effetto è quello che si continua a leggere dalla sorgente e a scrivere sul "Data0012" fino a che il ciclo IF non diventa VERO. Quando diventa VERO allora vuol dire che devo cambiare il file su cui scrivo, perchè quello precedente è finito.

E si continua così finche finisco di leggere tutto il file sorgente... e ovviamente, contemporaneamente, finisco di scriverlo nelle varie posizioni che mi servono. Nota: ovviamente il file sorgente è più piccolo di tutti i file "Data00XX" messi insieme.

/* last block */
read: "604160 Byte"
currentfile Data0015
jumpNhex: "2000"
write buffer

Questo è l'ultimo blocco e funziona circa come il primo. In pratica, ricordiamo che siamo usciti dal WHILE perchè io volevo leggere "835584 Byte" di fila... ma il file sorgente è finito prima. Questo blocco finale, mi va a leggere l'ultima parte di file sorgente e me la va a scrivere nel file "data0015" partendo da un certo puto. Niente di più.

/* Chiudi */
close all

_____________________________
Spero di essere stato abbastanza chiaro. Grazie a tutti per l'attenzione. Attendo consigli su come programmare tutto ciò.

ndakota
10-06-2010, 01:23
cut


Dove o come si impara questo? :cry:

PGI-Bis
10-06-2010, 05:45
Come premessa, adoro quando il forum non mi manda le notifiche di risposta ai thread, si fa sempre la figura di quello che ha lanciato il sasso per poi nascondere la mano. Sotto tutti a scrivere web application, funzionano che è una meraviglia. Fine premessa.

La logica che esponi è il frutto di un punto di vista procedurale. Che va benissimo ma non è per nulla divertente (anche se il divertimento è un concetto personale).

Funziona come descrizione di un fenomeno, e il mio ciarlare riguarda un tipo di approccio diverso alla sua interpretazione.

Ne faccio sempre una questione di pubblico ludibrio. Per quanto detto il programma potrebbe essere questo:

package xdataparser;

public class Main {

public static void main(String[] args) {
Factory factory = new Factory();
try {
BinaryDataOutput data0012 = factory.get(BinaryDataOutput.class, "xdataparser.Data0012");
BinaryDataOutput data0013 = factory.get(BinaryDataOutput.class, "xdataparser.Data0013");
BinaryDataOutput data0014 = factory.get(BinaryDataOutput.class, "xdataparser.Data0014");
BinaryDataOutput data0015 = factory.get(BinaryDataOutput.class, "xdataparser.Data0015");
BinaryDataInput extractedDat = factory.get(BinaryDataInput.class, "xdataparser.ExtractedDat");

DataParser headerParser = factory.get(DataParser.class, "HeaderParser");
DataParser bodyParser = factory.get(DataParser.class, "BodyParser");
DataParser footerParser = factory.get(DataParser.class, "FooterParser");

headerParser.execute(extractedDat, data0012);
bodyParser.execute(extractedDat, data0012, data0013, data0014);
footerParser.execute(extractedDat, data0015);
} finally {
factory.dispose();
}
}
}

Il suo funzionamento dipende poi da tanti altri pezzi, tutti molto piccoli ma questo rappresenta il suo "atomo", ciò che non può cambiare. E' anche un po' come vederlo dall'alto, si intuisce la forma generale a non se ne vedono i dettagli.

Completando i pezzi mancanti:

package xdataparser;

public class Factory {

public <T> T get(Class<T> type, String className) {
return null;
}

public void dispose() {}
}

package xdataparser;

public interface BinaryDataOutput {

}

package xdataparser;

public interface BinaryDataInput {

}

package xdataparser;

public interface DataParser {

void execute(BinaryDataInput in, BinaryDataOutput...out);
}

Diventa anche un programma perfettamente funzionante. Non fa una mazza di quello che vorremmo ma è compilabile ed eseguibile: come "programma" è completo.

A questo punto possiamo attaccarlo da dove preferiamo. Usando il motto "mai fare oggi quello che puoi rimandare a domani", partiamo dalla parte più facile: il parser dell'intestazione.

package xdataparser;

import java.nio.ByteBuffer;

public class HeaderParser implements DataParser {

/**
* Trasferisce i primi 339968 byte di una sorgente dati binaria in ciascuna
* delle destinazioni out. I dati sono scritti nelle destinazioni
* partendo dal byte di indice 0x896A000
* @param in la sorgente dati da cui trasferire i primi 339968 byte. Non può
* essere null.
* @param out una serie di destinazioni a cui trasferire i byte. Non può essere
* null, può essere vuoto.
*/
public void execute(BinaryDataInput in, BinaryDataOutput... out) {
ByteBuffer buffer = ByteBuffer.allocate(339968);
in.startAt(0).read(buffer);
for (BinaryDataOutput binaryDataOutput : out) {
binaryDataOutput.startAt(0x896A000).write(buffer);
}
}
}

Funziona? Se ci limitiamo al compito di esaminare il primo blocco se con "partendo dall'hex 896A000" intendiamo partendo dalla posizione 896A000 (e non dal primo intero trovato partendo dall'inizio del file il cui valore sia 896A000), direi di sì.

E 1/3 del programma è già fatto.

Passiamo al corpo, BodyParser. Il bello dei linguaggi di alto livello è che il PC fa quello che vogliamo, come lo vogliamo. Vogliamo leggere blocchi di 835584 byte? Possiamo farlo così:

package xdataparser;

import java.nio.ByteBuffer;

public class BodyParser implements DataParser {

public void execute(BinaryDataInput in, BinaryDataOutput... out) {
for(ByteBuffer chunk : in.startAt(339968).split(835584)) {

}
}

}

Ci sono lingue che permettono di scriverlo in forma più naturale, per Java direi che più di così non si possa. Naturalmente poi dovremo dire a BinaryDataOutput come fare quello che gli stiamo chiedendo ma se ha un senso a vederlo, si può fare.

Il codice alla fine sarà una cosa tipo:

chunkWriters.forFile(typefile).skip(skipAmount).write(chunk);

Ma rimando a domani il resto.

PGI-Bis
10-06-2010, 17:16
Questa parte ha un che di ipnotico.

/* Xnd block */
{While (read: "835584 Byte" != -1) /* fino a quando riesce a leggere 835.584 Byte di fila */
case: typefile = 1: currentfile Data0012;
if (1th-jump = 1): jumpNhex: "1000" & 1th-jump = 0
typefile = 2: open Data0013;
if (1th-jump = 1): jumpNhex: "2000" & 1th-jump = 0
typefile = 3: open Data0014;
if (1th-jump = 1): jumpNhex: "2000" & 1th-jump = 0
write buffer
jumpNhex: "1000"
if (jumpNhex = -1): typefile ++ & 1th-jump = 1 /* quando "salta" fuori dal file */
currentfile extracted.dat}

Se leggo correttamente, incrociando con la spiegazione, capita questo.

La sorgente ha un blocco centrale che inizia da 339968 e arriva fin dove posso leggere blocchi da 835584.

A questa sequenza di blocchi (SB) è applicata una funzione f che va da SB ad una destinazione dati D.

La funzione dice:

1. se è possibile far saltare in avanti D di 0x1000 byte, prendi un blocco da SB e scrivilo in D, nella posizione corrente + 0x1000
2. finchè è ulteriormente possibile far saltare in avanti D di 0x2000 bytes, prendi un blocco da SB e scrivilo in D, nella sua posizione corrente + 0x2000

Sia 1 che 2 sono ovviamente condizionati all'esistenza di un ulteriore blocco in SB.

Se così fosse (e dico se, per via dell'ipnosi), allora il parser dei blocchi centrali sarebbe:

partendo da 339968
data la sequenza di blocchi SB da 835584 byte disponibili nella sorgente
f(SB, Data0012)
f(SB, Data0013)
f(SB, Data0014)

Ammesso che l'interpretazione sia corretta, i giochi sarebbero fatti. Chiameremmo "f" ChunksWriter:

public class ChunksWriter {

public void writeChunks(Iterator<ByteBuffer> chunks, BinaryDataOutput out) {
if (chunks.hasNext() && out.canSkip(0x1000)) {
out.skip(0x1000).write(chunks.next());
}
while (chunks.hasNext() && out.canSkip(0x2000)) {
out.skip(0x2000).write(chunks.next());
}
}
}

E in body parser diremmo:

public class BodyParser implements DataParser {

public void execute(BinaryDataInput in, BinaryDataOutput... out) {
Iterator<ByteBuffer> chunks = in.startAt(339968).split(835584).iterator();
ChunksWriter writer = new ChunksWriter();
for (BinaryDataOutput binaryDataOutput : out) {
writer.writeChunks(chunks, binaryDataOutput);
}
}
}

Questo significa anche che la sorgente ha il seguente layout:

[inizio][corpo][fine][altro]

size = lunghezza in byte della sorgente dati
inizio: 339968 byte
corpo: FLOOR(size - 339968 / 835584) * 835584
fine: 604160 byte
altro: size - (inizio + corpo + fine)

Dal che ricaviamo che FooterParser piglia i byte da (inizio + corpo) a (inizio + corpo + 604160) e li infila in Data0015 partendo dal byte in posizione 0x2000.

public class FooterParser {

public void execute(BinaryDataInput in, BinaryDataOutput... out) {
int midBlockRegionSize = in.getSize() - 339968;
int blockCount = midBlockRegionSize / 835584;
int footerDataStart = 339968 + blockCount * 835584;
ByteBuffer footerData = ByteBuffer.allocate(604160);
in.startAt(footerDataStart).read(footerData);
for (BinaryDataOutput binaryDataOutput : out) {
binaryDataOutput.startAt(0x2000).write(footerData);
}
}
}

Quaglia? Se quaglia, il motore è a posto, si può già iniziare a pensare alla GUI.

Ing.StefanoM.
10-06-2010, 21:00
Si, la mia logica è procedurale e intrinsecamente non divertente. Perdonami, sono un ingegnere, quando mi è necessario spremere le meningi in un campo che non è il mio, amo il funzionale.

Sto leggendo quello che tu scrivi, però come già premesso, non sapendo proprio niente di programmazione "pura"... non sono in grado di capire se quello che scrivi può funzionare.

Però posso commentare le spiegazioni che tu dai, e lo faccio.

Quoto:
"Funziona? Se ci limitiamo al compito di esaminare il primo blocco se con "partendo dall'hex 896A000" intendiamo partendo dalla posizione 896A000 (e non dal primo intero trovato partendo dall'inizio del file il cui valore sia 896A000), direi di sì."

Risposta:
Con "partendo dall'hex 896A000" si intende la posizione esadecimale "896A000". Come regola generale di interpretazione: non si intendono mai valori di interi pari a qualsivoglia cifra, ma sempre posizioni.

Quoto:
"Se leggo correttamente, incrociando con la spiegazione, capita questo.
La sorgente ha un blocco centrale che inizia da 339968 e arriva fin dove posso leggere blocchi da 835584.
A questa sequenza di blocchi (SB) è applicata una funzione f che va da SB ad una destinazione dati D.
La funzione dice:
1. se è possibile far saltare in avanti D di 0x1000 byte, prendi un blocco da SB e scrivilo in D, nella posizione corrente + 0x1000
2. finchè è ulteriormente possibile far saltare in avanti D di 0x2000 bytes, prendi un blocco da SB e scrivilo in D, nella sua posizione corrente + 0x2000
Sia 1 che 2 sono ovviamente condizionati all'esistenza di un ulteriore blocco in SB."

Risposta 1:
Si, la sorgente ha un blocco "centrale" che parte dalla posizione "339968" e arriva praticamente fino a EOF (end of file). Questo bloccone va letto a pezzi da "835584". Il restante pezzettino che avanzerà, sarà processato in seguito dalla "parte ultima" del programma.
Risposta 2:
Si, il processo è corretto, però bisogna assolutamente stare attenti al primo salto che si effettua. Non è lo stesso per tutti e 3 i file "D" che vengono procesati dalla seconda parte del programma. Nello specifico. quando il file su cui sto scrivendo è "data0012" il primo salto deve essere da "hex 1000" e tutti quelli successivi come da standard ("hex 1000"); quando il file "target" è "data0013" il primo salto è "hex 2000"; quando il file "target" è "data0014" il primo salto è "hex 2000". Ovviamente, come tu ripeti, il tutto è anche condizionato dall'esistenza di un ulteriore blocco in SB.

Quoto:
"Dal che ricaviamo che FooterParser piglia i byte da (inizio + corpo) a (inizio + corpo + 604160) e li infila in Data0015 partendo dal byte in posizione 0x2000."

Risposta:
Perfetto.

Gentilmente, potrei ricevere il programma già compilato (oltre alla sorgente) in modo da procedere col testing ?

PGI-Bis
10-06-2010, 22:23
Il codice lo incollo più che altro per i terzi che leggono. Da te mi serve esattamente il commento alla spiegazione, perchè il codice non farà quello che vuoi tu ma quello che io ho capito di ciò che vuoi tu: se non ci intendiamo al millesimo di millimetro si perdono ore e ore cercando dei bug che non ci sono.

Si, il processo è corretto, però bisogna assolutamente stare attenti al primo salto che si effettua. Non è lo stesso per tutti e 3 i file "D" che vengono procesati dalla seconda parte del programma. Omissis.

Dunque il processo NON è corretto. Io intendevo, dato il famoso pacco di blocchi SB

1. trasferisci i dati da SB a Data0012: il primo blocco lo scrivi dopo aver saltato 0x1000 byte, i restanti saltando 0x2000 byte
2. fai la stessa cosa di prima per Data0013
3. fai la stessa cosa di prima per Data0014

Invece bisogna fare:

1. trasferisci i dati da SB a Data0012: il primo blocco lo scrivi dopo aver saltato 0x1000 byte, i restanti saltando ogni volta di 0x1000 byte
2. trasferisci i dati da SB a Data0013: il primo blocco lo scrivi dopo aver saltato 0x2000 byte, i restanti saltando ogni volta di 0x1000 byte
3. trasferisci i dati da SB a Data0014: come per Data0013.

Se va bene, ri-confermiamo i singoli passaggi. E' importante: un programmatore dovrebbe sempre sapere cosa scrivere PRIMA di scriverlo.

1. Trasferimento del primo blocco.

Prendo i primi 339968 byte da extracted.dat e li scrivo in Data0012 partendo dalla posizione 0x896A000. Cioè se questo è extracted.dat:

[0...339968][ALTRO]

Data0012 diventerà:

[0...0x896A000][dati di extracted.dat][ALTRO]

2. Trasferimento dei blocchi intermedi.

Prendo extracted.dat e parto dal byte di indice 339968. Da lì, finchè posso leggere da extracted.dat dei blocchi di 835584 byte:

A) prendo il primo blocco disponibile (cioè il primo in assoluto) e lo metto in Data0012, partendo dalla posizione in cui Data0012 si trova attualmente più 0x1000 byte, cioè 0x896A000 + 339968 + 0x1000, SE questo indice rientra nel range [0...numero di byte in Data0012];
B) Se il passaggio precedente è andato a buon fine, prendo il primo blocco disponibile (cioè il secondo) e lo metto in Data0012, partendo dalla sua posizione attuale (che sarebbe 0x896A000 + 339968 + 0x1000 + 835584) più 0x1000 SE questo punto di partenza rientra nel range [0...numero di byte in Data0012];
C) ripeto B, usando il blocco successivo (3°, 4°, 5° eccetera)

Esaurito Data0012 inizio con Data0013. Il procedimento è uguale MA il primo salto è di 0x2000 e non di 0x1000. Dal secondo in poi è invece di 0x1000

Esaurito Data0013 inizio con Data0014. Il procedimento è uguale a quello di Data0013, senza se e senza ma.

3. Trasferimento del blocco finale.

Prendo un pezzo particolare di extracted.dat che parte da X ed arriva a X + 604160. Se H è la dimensione dell'intestazione, B la dimensione di un blocco del corpo e L la lunghezza totale del file extracted.dat, X è:

X= H + ((L - H) / B) * B

[sfruttando il troncamento della divisione intera].

Quindi:

partendo da X prendo 604160 byte e li metto in Data0015 partendo da 0x2000.

Tutto ok? Confermi (conti compresi)? Il fatto che io cerchi di determinare dei valori assoluti per le posizioni a partire dalle quali scrivere dipende dal fatto che tanto minori sono le dipendenze di una parte del programma dallo stato di un'altra parte tanto maggiori sono le opportunità per il calcolatore di eseguire i calcoli in parallelo.

PGI-Bis
11-06-2010, 05:45
Vabbè.

Le "elucubrazioni strutturali" su cui ci siamo soffermati, concretamente, che vantaggi danno?

Uno solo ma è bello tosto: la combinabilità, ovvero la possibilità di collegare pezzi diversi del programma senza che questi pezzi si cementino. Dalla combinabilità (che è poi una modularità un po' più spinta) discende l'estendibilità.

Combinando i pezzi già scritti con i pezzi della gui di una tipica procedura guidata, salta fuori questo.

http://www.tukano.it/immagini/xdataparser/Schermata-XDataParser001.png

http://www.tukano.it/immagini/xdataparser/Schermata-XDataParser002.png

http://www.tukano.it/immagini/xdataparser/Schermata-XDataParser003.png

http://www.tukano.it/immagini/xdataparser/Schermata-XDataParser004.png

http://www.tukano.it/immagini/xdataparser/Schermata-XDataParser005.png

http://www.tukano.it/immagini/xdataparser/Schermata-XDataParser006.png

DanieleC88
11-06-2010, 18:11
:eekk:

Spero che fosse solo insonnia a farti postare a quell'ora.

PGI-Bis
11-06-2010, 18:59
Devo ammettere di avere notti poco serene. Non so se siano i 130 gradi o il 200% di umidità.

Ing.StefanoM.
11-06-2010, 19:24
Salto i convenevoli e passo ad analizzare le varie constatazioni.

"Invece bisogna fare:

1. trasferisci i dati da SB a Data0012: il primo blocco lo scrivi dopo aver saltato 0x1000 byte, i restanti saltando ogni volta di 0x1000 byte
2. trasferisci i dati da SB a Data0013: il primo blocco lo scrivi dopo aver saltato 0x2000 byte, i restanti saltando ogni volta di 0x1000 byte
3. trasferisci i dati da SB a Data0014: come per Data0013.

Se va bene, ri-confermiamo i singoli passaggi. E' importante: un programmatore dovrebbe sempre sapere cosa scrivere PRIMA di scriverlo."

Risposta: perfetto.

"1. Trasferimento del primo blocco.

Prendo i primi 339968 byte da extracted.dat e li scrivo in Data0012 partendo dalla posizione 0x896A000. Cioè se questo è extracted.dat:

[0...339968][ALTRO]

Data0012 diventerà:

[0...0x896A000][dati di extracted.dat][ALTRO]

2. Trasferimento dei blocchi intermedi.

Prendo extracted.dat e parto dal byte di indice 339968. Da lì, finchè posso leggere da extracted.dat dei blocchi di 835584 byte:

A) prendo il primo blocco disponibile (cioè il primo in assoluto) e lo metto in Data0012, partendo dalla posizione in cui Data0012 si trova attualmente più 0x1000 byte, cioè 0x896A000 + 339968 + 0x1000, SE questo indice rientra nel range [0...numero di byte in Data0012];
B) Se il passaggio precedente è andato a buon fine, prendo il primo blocco disponibile (cioè il secondo) e lo metto in Data0012, partendo dalla sua posizione attuale (che sarebbe 0x896A000 + 339968 + 0x1000 + 835584) più 0x1000 SE questo punto di partenza rientra nel range [0...numero di byte in Data0012];
C) ripeto B, usando il blocco successivo (3°, 4°, 5° eccetera)

Esaurito Data0012 inizio con Data0013. Il procedimento è uguale MA il primo salto è di 0x2000 e non di 0x1000. Dal secondo in poi è invece di 0x1000

Esaurito Data0013 inizio con Data0014. Il procedimento è uguale a quello di Data0013, senza se e senza ma."

Risposta: Perfetto, però c'è un "vizio di forma"; quando si parla della posizione "0x896A000 + 339968 + 0x1000" si stanno sommando 2 esadecimali e un decimale. Ma basta ricordarselo. Idem per la posizione "0x896A000 + 339968 + 0x1000 + 835584". Magari potrei essere stato solo io a non capire che fosse sottinteso che si vada prima a tradurre tutti in esadecimale (o decimale che sia).

"3. Trasferimento del blocco finale.

Prendo un pezzo particolare di extracted.dat che parte da X ed arriva a X + 604160. Se H è la dimensione dell'intestazione, B la dimensione di un blocco del corpo e L la lunghezza totale del file extracted.dat, X è:

X= H + ((L - H) / B) * B

[sfruttando il troncamento della divisione intera].

Quindi:

partendo da X prendo 604160 byte e li metto in Data0015 partendo da 0x2000."

Risposta estesa:
(L - H) / B, divisione intera -> restituisce il numero di blocchi (multiplo di 835584) da cui è composto il file, privato sia del blocco iniziale (causa L - H) sia della parte finale (causa divisione intera), essendo la parte finale inferiore a 835584.
H + ((L - H) / B) * B -> risulta quindi l'effettiva posizione di partenza dell'ultimo blocco.
Che poi è equivalente a dire: X = EOF - 604160.
Che "604160 bytes" fossero l'ultimo blocco della sorgente lo si capiva dal fatto che nella mia logica esiste la condizione per cui: SE NON puoi copiare altri 835584 bytes di seguito ESCI dal WHILE (è insito che la sorgente non contine più un blocco consecutivo di 835584, quindi sei arrivato a EOF - last block: last block < 835584).

Risposta breve: perfetto.

Rimango in attesa delle probabili conclusioni e nel frattempo ringrazio sentitamente Mr. PGI-Bis per la disponibilità e la signorilità.

PGI-Bis
11-06-2010, 19:55
Teoricamente adesso dovrei ripassarmi il codice per vedere che effettivamente faccia quello che è stato confermato ma rimando a stanotte (che già so sarà di ennesima passione).

Incollo un link per i test.

http://www.tukano.it/xdataparser/launch.jnlp

Uso un jnlp così gli aggiustamenti che faremo (ce ne sono sempre da fare) ti arrivano automaticamente, quando il test è finito incollo il sorgente ed un eseguibile off-line.

L'ultimo pulsante della GUI è "di bellezza": non fa null ma l'ho messo perchè potrebbe fare qualcosa di utile. Se i file che maneggi son sempre gli stessi la GUI potrebbe, a richiesta, memorizzare i percorsi, così da trovarli già inseriti all'avvio.

Il pulsante di backup l'ho messo perchè il programma ha delle potenzialità apocalittiche notevoli: personalmente ho cassato un paio di file che non avrei voluto propriamente eliminare. Il backup è opzionale perchè non conosco la dimensione dei file coinvolti. Se si tratta di qualche megabyte si può renderlo automatico, se sono decine di megabyte l'automatismo rischia di riempire l'hard disk di backup.

Attendo notizie.

Ing.StefanoM.
11-06-2010, 22:49
Il primo test è avvenuto con le seguenti modalità:

-3) Preparazione dei dati sorgente da "data0012" a "data0015".
-2) Estrazione del file "extracted.dat" dai file sorgente di cui sopra, attraverso programma già esistente in mio possesso.
-1) Constatazione della leggibilità del file "extracted.dat" estratto nel suddetto modo.

0) Modifica del file "extracted.dat" attraverso il programma di lettura/scrittura apposito. Differenza bytes dall'originale uguale a zero (modifiche comunque presenti a video).

1) Esecuzione del programma postato nel topic; selezionato come imput il file "extracted.dat" citato al punto 0 (e quindi modificato). Selezionati gli output: da "data0012" a "data0015". Eseguito il programma (no backup).

2) Ripetizione del punto -2.

3) Constatata la non leggibilità del file "2nd_extracted.dat".

Posto immagine, cui poi commento.

L'unica cosa che posso constatare è che i file "data00XX" assumono una dimensione finale alquanto sospetta. Dovrebbero infatti rimanaere inalterati. E' ovvio che poi ne risente il nuovo file "2nd_extracted.dat" (quello di verifica); non rimanendo più le sorgenti dello stesso tipo.

Sono disponibile volendo, in serata su MSN, per parlare direttamente della questione.

Saluti.