Toon posts:

[java] InputStreamReader met eigen InputStream blockt

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hoi,

Ik ben al twee uur aan het prutsen met het volgende: ik heb een eigen InputStream gemaakt, en deze voer ik vervolgens aan een InputStreamReader. Constructen gaat prima, echter zodra ik een read() doe op de InputStreamReader, blijft deze om een of andere reden doorlezen (continue read()'s dus) op mijn eigen InputStream, die na een tijdje natuurlijk gewoon blockt omdat er niet meer data is.

Tevens wordt het debuggen niet makkelijker gemaakt door het feit dat hoewel de InputStreamReader open source is, deze min of meer een closed-source library (sun.nio.cs.StreamDecoder) wrapped, waardoor ik niet kan zien hoe of wat.

Uiteraard heb ik ook zelf lopen zoeken naar een antwoord, maar ben enkel iemand met hetzelfde probleem tegengekomen.

De InputStream code (geknipte code, is een inner class):
Java:
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
    protected class RTProInputStream extends InputStream {
        protected byte[] currentPacketData;
        protected int atByte;
        
        public RTProInputStream() {
            this.currentPacketData = new byte[0];
            this.atByte = 0;
        }
        
        public int read() throws IOException {
            try {
                if (this.atByte >= currentPacketData.length) {
                    System.out.println("Retrieving new packet...");
                    Packet next = RTProPresentationLayer.this.transport.readPacket();
                    System.out.println("Got packet..." + next);
                    this.currentPacketData = next.getData();
                    this.atByte = 0;
                }
                byte b = this.currentPacketData[this.atByte++];
                System.out.println("input stream read: " + b); 
                return b;
            } catch (InterruptedException e) {
                return -1;
            }
        }
        
        public int available() throws IOException {
            int a = this.currentPacketData.length - atByte +
                    RTProPresentationLayer.this.transport.availableBytes();
            
            System.out.println("Available: " + a);
            return a;
        }
    }


De testcode:
Java:
1
2
3
4
5
6
7
8
9
// ...knip...
            InputStreamReader readert = new InputStreamReader(stack1.getInputStream());

            System.out.println("readln..");
            do {
                System.out.println("actual read: " + readert.read());
            } while (readert.ready());
            System.out.println("readln d..");
// ...knip

Het resultaat:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
readln..
Retrieving new packet...
Got packet...DataPacket [id: 0, type: 0, length: 12]
input stream read: 84
input stream read: 69
input stream read: 83
input stream read: 84
input stream read: 13
input stream read: 10
input stream read: 84
input stream read: 69
input stream read: 83
input stream read: 84
input stream read: 13
input stream read: 10
Retrieving new packet...
waarna er niks meer gebeurt. Nu staat er in InputStreamReader API wel vermeld:
Each invocation of one of an InputStreamReader's read() methods may cause one or more bytes to be read from the underlying byte-input stream. To enable the efficient conversion of bytes to characters, more bytes may be read ahead from the underlying stream than are necessary to satisfy the current read operation.
Echter, zie ik niet in waarom hij meer dan 10 bytes gaat lezen, aangezien hij dit ook niet doet als ik "stack1.getInputStream()' hierboven vervang door System.in.

Hopend dat iemand ziet wat fout gaat :). Alvast bedankt!

[ Voor 5% gewijzigd door Verwijderd op 18-05-2006 07:48 ]


  • The Fox NL
  • Registratie: Oktober 2004
  • Laatst online: 14-02 22:37
Ik zou die readert.ready() statement eerst doen voordat je read() doet.
ready() geeft true als je volgende read() niet zal blocken. Maar jij draait het om.

Verwijderd

Topicstarter
Hij mag ook best wel blocken, maar niet meer als ik de eerste lijn is binnengekomen. Op deze manier voorkom ik dat er niks gebeurt als er toevallig nog niks ontvangen is.

  • The Fox NL
  • Registratie: Oktober 2004
  • Laatst online: 14-02 22:37
Klopt je transport.availableBytes wel? (regel 29) Geeft ie niet teveel terug zodat de inputstreamreader denkt dat ie nog kan lezen?

En ik zou toch eerst readert.ready() te doen voordat je read() doet. Dat moet toch al, omdat ready() iets zegt over de volgende read(), als je het erna doet is het al te laat. Niet dat dat iets te maken heeft met je probleem denk ik, maar toch.

[ Voor 49% gewijzigd door The Fox NL op 19-05-2006 11:11 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 21-02 03:42
De kans is groot dat de InputStreamReader niet direct de read() methode aanroept, maar de varianten die een byte[] buffer accepteren. De implementatie die de InputStream daarvan geeft, gebruikt wel read() om die buffer te vullen maar doet niets met available() omdat 'ie altijd probeert de hele buffer te vullen.

Als dit inderdaad is wat er gebeurt, dan zul je read(byte[], int, int) moeten overloaden, zodat 'ie niet blockt (tenzij er helemaal geen data beschikbaar is -- read() zou namelijk geen 0 moeten retourneren maar ofwel -1 bij EOF óf een geldige buffer).