Scrittura su file modalità binaria

Ciao a tutti,
ho da poco scoperto il modno di ruby e devo capire ancora molte cose.
Ad esempio una di queste riguarda la scrittura a file.
Dopo opportune elaborazioni ottengo una stringa di bit lunga un bel
pò…
Per salvare la stringa su file ho usato:

output = File.open(ARGV[1], “wb”)
output.write(varbit)

il risultato è un file che contiene la stringa di bit ma immenso perchè
ogni bit è scritto come carattere quindi se ho 10000 bit, ottengo 10000
caratteri cioè un file grande 10KB mentre volevo ottenere un file di
1250 caratteri quindi 1.2KB circa…
In pratica la scrittura raggruppata a 8 bit alla volta cioè un carattere
ASCII,
es:
101001010101010110010101001010111101001

ottengo:
101001010101010110010101001010111101001
ma scritta come: 000000001 + 00000000 + 000000001 + …
cioè ‘1’+‘0’+‘1’…
mentre vorrei: 10100101 + 01010101 + …
cioè: ‘Â¥’ + ‘U’ + …
nel file
Come si fa?!

Grazie

Fabio

Vedi Array#pack

Il 27 gennaio 2010 11.25, Fabio – [email protected] ha scritto:

il risultato è un file che contiene la stringa di bit ma immenso perchè
ogni bit è scritto come carattere quindi se ho 10000 bit, ottengo 10000
cioè ‘1’+‘0’+‘1’…


Ml mailing list
[email protected]
http://lists.ruby-it.org/mailman/listinfo/ml


Carlo P.
email: [email protected]
twitter: @carlopecchia

On Wednesday 27 January 2010 11:25:44 Fabio – wrote:

Dopo opportune elaborazioni ottengo una stringa di bit lunga un bel
pò…
[…]
Come si fa?!

Prova a dare un’occhiata a Array#pack ed a String#unpack:

Ciao
Flavio

2010/1/27 Fabio – [email protected]:

Ciao a tutti,
ho da poco scoperto il modno di ruby e devo capire ancora molte cose.
Ad esempio una di queste riguarda la scrittura a file.
Dopo opportune elaborazioni ottengo una stringa di bit lunga un bel
pò…
Per salvare la stringa su file ho usato:

output = File.open(ARGV[1], “wb”)
output.write(varbit)

hai frainteso: la modalità binaria di scrittura e lettura dei file è
una cosa diversa che ha a che fare con il fatto che i sistemi
operativio differiscono nel modo in cui trattano i file se sono testo
o “binari”. Quindi se scrivi un file di test è ok ‘w’ sennò meglio
‘wb’ (ma mi pare che ruby lo faccia in automatico ormai? Non ricordo).

Non mi è ben chiaro cosa devi fare ma dovresti applicare al contrario
la procedura che hai usato per creare la string “01110” (le classi
numeric mi pare abbiano una cosa del genere) per ottenere un oggetto
(e.g. un carattere o un numero) e poi scrivere quello. O meglio,
evitare la prima e la seconda operazione e passare direttamente da
input binario, manipolazione, scrittura.

2010/1/27 Fabio – [email protected]:

Vorrei che scrivesse gli equivalenti dei caratteri formati dai
raggruppamenti di 8 bit alla volta: ad esempio se ottengo la stringa di
bit 01000000, nel file mi viene scritto: “01000000” ma si tratta di 8
caratteri cioè 8 byte giusto? (‘0’=00000000, ‘1’=00000001, ecc…).
Io vorrei ottenere “a” (valore in ascii di 01000000) cioè 1 byte, ok?!

si, ma non capisco perché hai bisogno dei bit in una stringa

Ma ti dicevo: se hai ottenuto la string in un modo puoi applicare
l’ìoperazione inversa. Esempio, se hai usato Numebr#to_s(base) e
String#to_i(base), e ?carattere e Number#chr

?a.to_s(2)
=> “1100001”
?a.to_s(2).to_i(2).chr
=> “a”

Ecco… non riesco a capire perchè non lo fa in automatico e non riesco
a trovare niente che lo faccia…

ti avevano suggerito array pack e unpack che penso funzionino, sennò
vedi sopra. Il motivo per cui non lo fa in automatico è che tu gli
stai dicendo di scrivere una lista di caratteri. Dovrebbe poterti
leggere nel pensiero per poter capire che tu quella stringa di
caratteri ascii vuoi che sia interpretata come una stringa di bit :).

Come ti dicevo, il “binary” mode è un’altra cosa, significa solo che
su windows quando scrivi
file.puts(“ciao\nmiao”)
nel file di output c’è la stringa “ciao” seguita da un carattere di
new line mentre se apri il file in modalità non binaria nel file di
output avrai “ciao” seguito da un carriage return e poi da un newline.

hai frainteso: la modalit� binaria di scrittura e lettura dei file �
una cosa diversa che ha a che fare con il fatto che i sistemi
operativio differiscono nel modo in cui trattano i file se sono testo
o “binari”. Quindi se scrivi un file di test � ok ‘w’ senn� meglio
‘wb’ (ma mi pare che ruby lo faccia in automatico ormai? Non ricordo).

Non mi � ben chiaro cosa devi fare ma dovresti applicare al contrario
la procedura che hai usato per creare la string “01110” (le classi
numeric mi pare abbiano una cosa del genere) per ottenere un oggetto
(e.g. un carattere o un numero) e poi scrivere quello. O meglio,
evitare la prima e la seconda operazione e passare direttamente da
input binario, manipolazione, scrittura.

Brevemente, una volta ottenuta la stringa di bit, vorrei memorizzarla su
file, che alla fine sarebbe un file di testo, ma NON con scritto tutti 0
o 1.
Vorrei che scrivesse gli equivalenti dei caratteri formati dai
raggruppamenti di 8 bit alla volta: ad esempio se ottengo la stringa di
bit 01000000, nel file mi viene scritto: “01000000” ma si tratta di 8
caratteri cioè 8 byte giusto? (‘0’=00000000, ‘1’=00000001, ecc…).
Io vorrei ottenere “a” (valore in ascii di 01000000) cioè 1 byte, ok?!

Ecco… non riesco a capire perchè non lo fa in automatico e non riesco
a trovare niente che lo faccia…

In generale (questo vale per tutti i linguaggi) scrivere un file in
binario non vuol dire che Ruby ti converta stringhe di zeri e uni in
byte mentre scrive i dati nel file. Vuol dire che la stringa viene
scritta così com’è senza eventuali conversioni che il sistema operativo
applica ai file di testo (ce ne sono alcuni che ne fanno).

Quindi devi prima convertire la tua stringa in una sequenza di byte e
poi scriverla.

[“01000001”].pack(“B8”) ritorna “A”

[“01000001”, “01000010”].pack(“B8B8”) ritorna “AB”

pack è un metodo di Array e quindi per prima cosa dovrai spezzare la tua
stringa in blocchi di 8 caratteri e metterli in un array per cui
converrà produrre direttamente quello anziché la stringa.

Paolo

Brevemente, una volta ottenuta la stringa di bit, vorrei memorizzarla su
file, che alla fine sarebbe un file di testo, ma NON con scritto tutti 0
o 1.
Vorrei che scrivesse gli equivalenti dei caratteri formati dai
raggruppamenti di 8 bit alla volta: ad esempio se ottengo la stringa di
bit 01000000, nel file mi viene scritto: “01000000” ma si tratta di 8
caratteri cioè 8 byte giusto? (‘0’=00000000, ‘1’=00000001, ecc…).
Io vorrei ottenere “a” (valore in ascii di 01000000) cioè 1 byte, ok?!

Ecco… non riesco a capire perchè non lo fa in automatico e non riesco
a trovare niente che lo faccia…

2010/1/27 Paolo M. [email protected]:

In generale (questo vale per tutti i linguaggi) scrivere un file in
binario non vuol dire che Ruby ti converta stringhe di zeri e uni in
byte mentre scrive i dati nel file. Vuol dire che la stringa viene
scritta così com’è senza eventuali conversioni che il sistema operativo
applica ai file di testo (ce ne sono alcuni che ne fanno).

a riguardo, ci fu una volta un thread su ruby lang, che è molto
interssante perché si tende a pensare sia scemo windows, ma la cosa è
molto più antica
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/265722

gabriele renzi wrote:

2010/1/27 Fabio – [email protected]:

Vorrei che scrivesse gli equivalenti dei caratteri formati dai
raggruppamenti di 8 bit alla volta: ad esempio se ottengo la stringa di
bit 01000000, nel file mi viene scritto: “01000000” ma si tratta di 8
caratteri cioè 8 byte giusto? (‘0’=00000000, ‘1’=00000001, ecc…).
Io vorrei ottenere “a” (valore in ascii di 01000000) cioè 1 byte, ok?!

si, ma non capisco perché hai bisogno dei bit in una stringa

Ma ti dicevo: se hai ottenuto la string in un modo puoi applicare
l’ìoperazione inversa. Esempio, se hai usato Numebr#to_s(base) e
String#to_i(base), e ?carattere e Number#chr

?a.to_s(2)
=> “1100001”
?a.to_s(2).to_i(2).chr
=> “a”

Ecco… non riesco a capire perchè non lo fa in automatico e non riesco
a trovare niente che lo faccia…

ti avevano suggerito array pack e unpack che penso funzionino, sennò
vedi sopra. Il motivo per cui non lo fa in automatico è che tu gli
stai dicendo di scrivere una lista di caratteri. Dovrebbe poterti
leggere nel pensiero per poter capire che tu quella stringa di
caratteri ascii vuoi che sia interpretata come una stringa di bit :).

Come ti dicevo, il “binary” mode è un’altra cosa, significa solo che
su windows quando scrivi
file.puts(“ciao\nmiao”)
nel file di output c’è la stringa “ciao” seguita da un carattere di
new line mentre se apri il file in modalità non binaria nel file di
output avrai “ciao” seguito da un carriage return e poi da un newline.

Hai perfettamente ragione, quindi, mi spiego meglio.
Si tratta di un compressore (huffman).
Leggo in input un file di testo ed ottengo in uscita la sua versione
compressa.
Per com’è costruito ottengo una stringa lunghissima di bit ed un albero
delle decisioni.
Il problema è che se vado a salvare la stringa su file (essendo scritta
in caratteri ‘1’ e ‘0’) il file è più grosso dell’originale e quindi
sembra che non abbia compresso una mazza! In realtà se i bit fossero
raggruppati e scritti come caratteri occuperebbero 1/8 dello spazio e la
dimensione tornerebbe…
es:
fileinput.txt 182 KB
fileoutput.hfm 799 KB (???) no dovrebbe essere 799/8 → 99 KB OK!!!

Spero di aver chiarito il tuo dubbio…

Grazie a tutti per le risposte.

Fabio