Toon posts:

[Java] Schrijven naar bestand vanuit Servlet

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben voor school met een opdrachtje bezig die hits moet bijhouden voor een website. Een beetje loos om dat nou met een Servlet te gaan doen (kan volgens mij veel makkelijker), maar goed, 't moet maar.

Nou heb 'k een hele mooie Data class geschreven welke de gegevens bewaart en deze op schijf kan opslaan. Dat werkt prima standalone, maar op m'n server werkt 't dus niet. Ik moet de data echter wel persistent kunnen maken, zodat de hitcounts niet verdwijnen bij het restarten van de server.

Heb al meerdere dingen geprobeerd. Een FileWriter, een FileOutputStream met een PrintWriter en een FileOutputStream met een PrintStream. Echter, het bestand wordt nooit aangemaakt, terwijl de methode met de code wel wordt aangeroepen. Een probleem dus. Iemand die me hier kan helpen?

  • Feyd-Rautha
  • Registratie: November 2001
  • Laatst online: 02-08-2025
Heb je wel de nodige schrijfrechten op die directory ? En welke foutmelding heeft hij ?

I must not fear. Fear is the mind-killer. Fear is the little-death that brings total obliteration. I will face my fear. I will permit it to pass over me and through me. Where the fear has gone there will be nothing. Only I will remain.


Verwijderd

toevallig niet vergeten flush() aan te roepen als je klaar bent met schrijven?

Verwijderd

Topicstarter
Feyd-Rautha schreef op 03 October 2003 @ 16:21:
Heb je wel de nodige schrijfrechten op die directory ? En welke foutmelding heeft hij ?
Mjah, probleem is dus, 'k krijg helemaal geen foutmelding. Er staat niks in de logs, krijg geen foutmelding in m'n browser, 'k zie gewoon helemaal niks. Maar 't bestand bestaat dus simpelweg niet (heb ook al gezocht er naar).

Wat die schrijfrechten betreft? 'k heb geen flauw idee hoe dat precies zit. Heb Tomcat onder Windhoos draaien. Ook geen flauw idee waar ie 't bestand eigenlijk neer wil zitten.

Overigens heb 'k autoFlush op true gezet, dus volgens mij moet dat 't probleem niet zijn.

  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Heb je eventuele excepties wel netjes afgehandeld? Laat anders (de relevante delen van) je code eens zien.

Verwijderd

Topicstarter
Hmmz, okeej, ffies wat code:

code:
1
private File storageFile = new File("HitCounter.dat");


Dit is een instance variable in m'n Servlet.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Data hits = (Data) this.getServletContext().getAttribute("hits");

// Als er nog geen data structuur aanwezig is
if (hits == null) 
{
    // Als het bestand bestaat
    if (storageFile.exists()) 
    {
        // Maak de datastructuur aan op basis van het gevonden bestand en sla deze op op applicatie niveau
        hits = new Data(storageFile); 
        this.getServletContext().setAttribute("hits", hits);
    }
    else // Als er nog geen data bestand is voor de data structuur 
    {
        // Maak een lege datastructuur aan en sla deze op op applicatie niveau
        hits = new Data();
        this.getServletContext().setAttribute("hits", hits);
    }
}


Hier kijk ik eerst of er op applicatie niveau al een variable is voor 't opslaan van data. Zo niet, dan wordt gecontroleerd of er een bestand bestaat waarin de data is opgeslagen. Zo ja, dan wordt 't object van die data gemaakt, zo niet, dan wordt een leeg object gemaakt.

code:
1
hits.Save(storageFile);


Hier sla ik de data op (methode volgt zo). Dit gebeurt na elke registratie van een hit.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public Data(File storageFile) throws IOException 
{
    // Open the file
    BufferedReader reader = new BufferedReader(new FileReader(storageFile));

    // Read the header
    StringTokenizer tokenizer = new StringTokenizer(reader.readLine(), "|");

    // Get the total amount of hits, browsers, language codes, IP addresses and days from the read line
    totalHits = Integer.parseInt(tokenizer.nextToken());
    int browsers = Integer.parseInt(tokenizer.nextToken());
    int languages = Integer.parseInt(tokenizer.nextToken());
    int ipaddresses = Integer.parseInt(tokenizer.nextToken());
    int days = Integer.parseInt(tokenizer.nextToken());
        
    // Read the browser types and their hits from the file
    for (int a = 0; a < browsers; a++) 
    {
        tokenizer = new StringTokenizer(reader.readLine(), "|");
            hitsPerBrowser.put(tokenizer.nextToken(), Integer.decode(tokenizer.nextToken()));
    }

    // Read the language codes and their hits from the file
    for (int a = 0; a < languages; a++) 
    {
        tokenizer = new StringTokenizer(reader.readLine(), "|");
        hitsPerLanguage.put(tokenizer.nextToken(), Integer.decode(tokenizer.nextToken()));
    }

    // Read the IP addresses and their hits from the file
    for (int a = 0; a < ipaddresses; a++) 
    {
        tokenizer = new StringTokenizer(reader.readLine(), "|");
        hitsPerIP.put(tokenizer.nextToken(), Integer.decode(tokenizer.nextToken()));
    }

    // Read the unique hits per day from the file
    for (int a = 0; a < days; a++) 
    {
        tokenizer = new StringTokenizer(reader.readLine(), "|");
        uniqueHitsPerDay.put(tokenizer.nextToken(), Integer.decode(tokenizer.nextToken()));
    }

    // Close the file
    reader.close();
}


Dit is de code om 't Data object te maken vanuit data op de schijf.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public boolean Save(File storageFile) {
    try {
        // Create a FileWriter for the file, so we can write data to it
        FileOutputStream fs = new FileOutputStream(storageFile, false);
        PrintStream writer = new PrintStream(fs);

        // Write a header to the file
        writer.println(totalHits + "|" + hitsPerBrowser.keySet().size() + "|" + hitsPerLanguage.keySet().size() + "|" +
        hitsPerIP.keySet().size() + "|" + uniqueHitsPerDay.keySet().size() + "\r\n");

        // Write the browser types and hits to the file
        Iterator i = hitsPerBrowser.entrySet().iterator();
        while (i.hasNext()) {
            Map.Entry entry = (Map.Entry) i.next();
            writer.println(entry.getKey() + "|" + entry.getValue() + "\r\n");
        }

        // Write the language codes and hits to the file
        i = hitsPerLanguage.entrySet().iterator();
        while (i.hasNext()) {
            Map.Entry entry = (Map.Entry) i.next();
            writer.println(entry.getKey() + "|" + entry.getValue() + "\r\n");
        }

        // Write the IP addresses and hits to the file
        i = hitsPerIP.entrySet().iterator();
        while (i.hasNext()) {
            Map.Entry entry = (Map.Entry) i.next();
            writer.println(entry.getKey() + "|" + entry.getValue() + "\r\n");
        }

        // Write the unique hits per day to the file
        i = uniqueHitsPerDay.entrySet().iterator();
        while (i.hasNext()) {
            Map.Entry entry = (Map.Entry) i.next();
            writer.println(entry.getKey() + "|" + entry.getValue() + "\r\n");
        }

        // Close the file
        writer.close();

        // Return true
        return true;
    }
    catch (IOException ex) {
        return false;
    }
}


En tot slot de code voor het schrijven van het bestand.

  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023
Je handelt dus inderdaad de excepties niet goed af. In Save "return false" bij een IOException en vervolgens niets met de return value doen. Ik zie ook geen afhandeling van de IOException die de constructor van Data kan gooien. Daar zou ik dus eerst iets aan doen.

Om te achterhalen waar het bestand zal worden opgeslagen kun je trouwens de methode getAbsolutePath van File gebruiken.

Verwijderd

Topicstarter
Hmmz, wat doet de aanroepende functie van doGet met een Exception die gethrowt wordt dan? Aangezien doGet nu IOException throwt en de Save method nu ook (heb 'k ffies aangepast) moet een eventueel optredende Exception toch ergens moeten blijven dacht ik zo?

Verwijderd

Weet jij waar je bestand belant als je new File("blabla.dat") gebruikt? In welke directory? Vast niet, het is daarom verstandig om of een absoluut pad op te geven of files te verkrijgen dmv servletcontext.getResource() (of iets van die strekking, ik kan het hier zo snel even niet opzoeken, maar het zit in het ServletContext object dacht ik).

  • marcusk
  • Registratie: Februari 2001
  • Laatst online: 26-09-2023

  • PommeFritz
  • Registratie: Augustus 2001
  • Laatst online: 10-07 04:13

PommeFritz

...geen friet

Pas op; getRealPath() werkt soms niet: "This method returns null if the servlet container cannot translate the virtual path to a real path for any reason (such as when the content is being made available from a .war archive". Het gaat bijvoorbeeld mis onder bepaalde versies van BEA Weblogic.

FireFox - neem het web in eigen hand


  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Test nou met wat simpels. Gewoon puur een bestandje en daar 1337 in schrijven. Kijk eerst of dat lukt en ga dan uitbreiden.

En bij Resin (ik weet niet wat jij gebruikt) worden bestandjes zonder pad in de minst diep map van Resin geplaatst.

{signature}

Pagina: 1