06. november 2004 - 20:33Der er
11 kommentarer og 1 løsning
Skriving (til fil) af String's og double's i faste positioner
Nok lidt et overordnet spm.
Jeg ønsker at skrive karakterer (String's) og numeriske variable (double's) til en fil og ønsker at gøre det således, at længden af hver "record" altid er den samme.
Jeg er med på, at jeg på forhånd er nødt til at specificere den maksimale længde af mine String's, men hvordan forholder det sig med skrivning af double's og disses "længde"?
Hvis jeg helt dumt skriver til en OutputStream vil de enkelte "records" få forskellig længde, men jeg ønsker hver gang at såvel mine String's som double's får "fuld længde", så mine "records" alle får samme længde i sidste ende.
DecimalFormat har vist et problem med leading spaces.
Men så kombinerer du bare !
import java.text.*;
public class DFormat { public static void main(String[] args) { DecimalFormat df = new DecimalFormat("#.00"); for(int i = 0; i < 5; i++) { String s = df.format(Math.exp(i)); s = " ".substring(s.length()) + s; System.out.println(s); } } }
-> arne_v: Du skriver at double altid er 8 bytes. Formatet, som double gemmes i, afhænger vel af, om man skriver til en tekst- eller en binary-fil eller? Såfremt man gemmer i en binary-fil, hvordan gemmer man så en double, så den fylder mindst muligt og alligevel har samme længde uanset værdien? (når man gemmer tal, går jeg ud fra, at det er mest pladsbesparende at gemme som binary)
-> arne_v: Ja, hvis man skriver til DataOutputStream er det sådan, at den fysiske repræsentation er i 256-decimalsystem (00-FF i hex), hvor char fylder 2 bytes (svarende til et værdispænd på 256**2=65.536 eller [0;65.535]), int fylder 4 bytes (svarende til et værdispænd på 256**4=4.294.967.296 eller [-2.147.483.648;2.147.483.647]), double fylder 8 bytes svarende til et værdispænd på 256**8=1.84E19) osv., dvs. numeriske størrelser har fast længde. Strenge derimod har i sagens natur variabel længde.
Når man skriver til DataOutputStream, kan man bruger metoderne writeInt(), WriteDouble() osv., og længden bliver den rigtige. Hvis man yderligere ønsker at skrive tekst, kan man bruge metoden writeUTF().
Ved genindlæsning kan man så bruge DataInputStream og de tilsvarende read()-metoder.
Hvad der umiddelbart undrede mig var, hvordan Java ved genindlæsning holder styr på data, når der er tekst af variabel længde inkluderet (det er selvfølgelig oplagt, hvis der kun er tale om numeriske felter med fast længde, jf. ovenfor). Pointen her er vel, at Unicode-karakterer fysisk i output-filen repræsenteres ved karakterer, der alle afviger fra de karakterer, som de numeriske størrelser lagres med. Når der så læses Unicode-tekst med readUTF(), læses der indtil der ikke er flere Unicode-karakterer.
Jeg kan ikke forestille mig, at den samme funktionalitet ville være mulig, hvis man skrev tekst med writeBytes() eller writeChars().
public final void writeUTF(String str) throws IOException
Writes a string to the underlying output stream using Java modified UTF-8 encoding in a machine-independent manner.
First, two bytes are written to the output stream as if by the writeShort method giving the number of bytes to follow. This value is the number of bytes actually written out, not the length of the string. Following the length, each character of the string is output, in sequence, using the modified UTF-8 encoding for the character. If no exception is thrown, the counter written is incremented by the total number of bytes written to the output stream. This will be at least two plus the length of str, and at most two plus thrice the length of str.
-> arne_v: Det er vel rigtigt, at int kun antager værdier i intervallet [-2.147.483.648;2.147.483.647]? Prøver man med int i = 2147483648; får man fejlen "integer too large".
Ja, det kan jeg godt se mht. writeUTF. De to første bytes i output-filen er reserveret til styring.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.