Avatar billede jespersahner Nybegynder
06. november 2004 - 20:33 Der 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.
Avatar billede arne_v Ekspert
06. november 2004 - 20:36 #1
Jeg formoder at det er en tekst fil du skriver. Ellers er double altid 8 bytes.

Java 1.5 (5.0):
  brug printf

ældre Java:
  kald toString metoden og pad selv med det nødvendig blanke
eller
  kig på DecimalFormat
Avatar billede arne_v Ekspert
06. november 2004 - 20:42 #2
Hm.

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);
        }
    }
}

giver:

      1.00
      2.72
      7.39
    20.09
    54.60
Avatar billede jespersahner Nybegynder
07. november 2004 - 01:33 #3
-> 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)
Avatar billede arne_v Ekspert
07. november 2004 - 09:05 #4
Det er kun ved binært at double altid er 8 bytes.

Hvis du vil skrive en binær fil er en DataOutputStream et godt valg.

En binær fil er hurtigst. Om den fylder mindst afhænger af antal cifre i tekst format.
Avatar billede arne_v Ekspert
07. november 2004 - 09:06 #5
PS: DataOutputSTream skriver big endian !
Avatar billede jespersahner Nybegynder
07. november 2004 - 10:33 #6
-> 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().

Har du nogle kommentarer vedr. dette?
Avatar billede arne_v Ekspert
07. november 2004 - 10:52 #7
De 4 byte i en int kan antale ale værdier, så det kan ikke ære helt sådan.

writeUTF må enten skrive en længde først eller bruge et terminator tegn.
Avatar billede arne_v Ekspert
07. november 2004 - 10:53 #8
Det er længde !

Fra docs:

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.
Avatar billede jespersahner Nybegynder
07. november 2004 - 11:26 #9
-> 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.
Avatar billede arne_v Ekspert
07. november 2004 - 11:34 #10
Ja.

Men det interval gør også at de 4 bytes kan antage alle mulige værdier. Og at der
ikke kan kendes forskel påint og char's udfra værdierne.
Avatar billede arne_v Ekspert
21. november 2004 - 20:25 #11
OK ?
Avatar billede jespersahner Nybegynder
21. november 2004 - 21:03 #12
->arne_v: Jep :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester