[Java/MSNP7] Aantal bytes van (UTF-8) tekens

Pagina: 1
Acties:

  • mEdnass
  • Registratie: November 2001
  • Laatst online: 04-12-2021
Momenteel ben ik bezig met een botje voor MSN. Het gaat allemaal geweldig, MSNP7 is niet zo moeilijk :P De bot is in het stadium dat ie automagisch inlogt, vriendenlijstveranderingen verwerkt, berichten kan sturen én ontvangen. Hoewel, die laatste twee niet helemaal.
Als je een bericht binnenkrijgt van een bepaalde gebruiker komt er bijv. het volgende lijntje tekst binnenrollen: "MSG sjakie@hotmail.com Sjakie 124". MSG geeft aan dat er een bericht aankomt, daarna het passport van de gebruiker en zijn schermnaam. Als laatste is het aantal bytes van het bericht dat eraan komt.
code:
1
2
3
4
5
6
MSG sjakie@hotmail.com Sjakie 124\r\n
MIME-Version: 1.0\r\n
Content-Type: text/plain; charset=UTF-8\r\n
X-MMS-IM-Format: FN=MS%20Serif; EF=; CO=; CS=0; PF=22\r\n
\r\n
hee Ed!

"\r" en "\n" staan er voor de duidelijkheid even bij ;), ze tellen ieder als 1 byte...
In java maak ik gebruik van een standaard socketverbinding en daaruit gemaakte IO-streams:
code:
1
2
in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));

Als ik nu met een loopje 124x een karakter uitlees dmv "stringBuffer.append((char) in.read())" kom ik precies uit en is iedereen tevree :7
Het probleem:
Als onze Sjakie nu besluit om streepjes op de e te gaan zetten gaat het mis :(:
code:
1
2
3
4
5
6
MSG sjakie@hotmail.com Sjakie 126\r\n
MIME-Version: 1.0\r\n
Content-Type: text/plain; charset=UTF-8\r\n
X-MMS-IM-Format: FN=MS%20Serif; EF=; CO=; CS=0; PF=22\r\n
\r\n
héé Ed!

Het aantal karakters is nu dus ineens minder dan het aantal bytes :? Leuker wordt het nog met de Euro, want:
code:
1
2
3
4
5
6
MSG sjakie@hotmail.com Sjakie 122\r\n
MIME-Version: 1.0\r\n
Content-Type: text/plain; charset=UTF-8\r\n
X-MMS-IM-Format: FN=MS%20Serif; EF=; CO=; CS=0; PF=22\r\n
\r\n
€40

Die telt ineens als 3 bytes :?
Dit gaat dus helemaal de soep in, want de in.read() methode blockt nu, omdat er verder niks meer is :| Ook tijdens het maken van een bericht(dan moet ik het aantal bytes van een string weten...) gaat dit fout. Is er een (nette) manier om hieromheen te werken? Of, anders gevraagd: Hoe kan ik weten hoeveel bytes een bep. char inneemt? Dan kan ik op een zinnige manier een teller bijhouden om te kijken of ik al aan 't eind zit :P

edit:

/me is perfectionist :P, zag een piepklein foutje :D

  • NDF82
  • Registratie: Januari 2002
  • Laatst online: 26-08 21:49

NDF82

Doomed Space Marine

Kijk is naar DataInputStream.

code:
1
2
read(byte[] b) 
Reads some number of bytes from the contained input stream and stores them into the buffer array b.


je kunt hiermee het aantal bytes dat je wilt inlezen(arraysize) en er is vast wel een klasse om die byte-array om te zetten naar een UTF-8 string. Laat het even weten als het gelukt is, ben er namelijk ook mee bezig :D

Pentium 233MHz MMX + Diamond Monster 3D 3DFX Voodoo II


  • mEdnass
  • Registratie: November 2001
  • Laatst online: 04-12-2021
Krijg nou wat ! :D
Java Documentatie: Class DataInputStream
All characters in the range '\u0001' to '\u007F' are represented by a single byte:

The null character '\u0000' and characters in the range '\u0080' to '\u07FF' are represented by a pair of bytes:
Characters in the range '\u0800' to '\uFFFF' are represented by three bytes:

The two differences between this format and the "standard" UTF-8 format are the following:

The null byte '\u0000' is encoded in 2-byte format rather than 1-byte, so that the encoded strings never have embedded nulls.
Only the 1-byte, 2-byte, and 3-byte formats are used.
Nou weet ik iig waardoor het komt =)
edit:
Misschien is het ook wel beter te testen of een karakter binnen deze grenzen ligt en daar iets mee te doen. In de rest van mijn klassen gebruik ik nl gewoon in.readLine(); Die is wat efficiënter, dacht ik. Die is hier niet te gebruiken, want het bericht eindigd zonder \r\n :( en bij het versturen werkt het al helemaal niet ;)

  • TheOneLLama
  • Registratie: Oktober 2000
  • Laatst online: 20-01-2022

TheOneLLama

A llama like no llama before

Weet je zeker dat het MSN protocol met UTF8 werkt? Zo ja dan is het behoorlijk stom van ze dat ze binary framing met aantallen in bytes gebruiken.. Als dat zo is dan is dat behoorlijk raar van ze :) Maar goed als oplossing kun je je inkomende data als er een message is ipv via je BufferedReader gewoon via de inputstream lezen en in een byte array zetten. DIe bytearray kun je dan weer via je een UTF-8 inputstream lezen met een ByteArrayInputStream.

Opera OpenOffice.org Jabber Psi jabber://llama@mordax.com


  • mEdnass
  • Registratie: November 2001
  • Laatst online: 04-12-2021
TheOneLLama,
Ik had ook liever gezien dat ze gewoon het aantal chars gaven ;) En ja, het moet wel UTF-8 zijn: "Content-Type: text/plain; charset=UTF-8" :P
En bedoel je nou dat ik 2 filters op 1 inputstream moet gaan hangen? Weet niet zeker, maar volgens mij werkte dat niet echt lekker. De bufferedreader trok em voor mijn neus leeg ofzo. Maar daar kan ik ook helemaal naast zitten =)

edit:

Okay! Ik heb het min of meer :P
Bij het ontvangen controleer ik gewoon of ie tussen die bepaalde waardes ligt(zie 2e post hierboven... en bij versturen:
code:
1
2
3
4
5
6
7
int numBytes = -2;
String s = "één";
try {
     numBytes = s.getBytes("UTF-8").length;
} catch (UnsupportedEncodingException e) {}

System.out.println(numBytes );

Tadaa!!! :D 8)

  • TheOneLLama
  • Registratie: Oktober 2000
  • Laatst online: 20-01-2022

TheOneLLama

A llama like no llama before

mEdnass schreef op 15 augustus 2002 @ 13:44:
TheOneLLama,
Ik had ook liever gezien dat ze gewoon het aantal chars gaven ;)
Tja de designers hadden meer C/C++ in hun hoofd dan JAVA waarschijnlijk
En ja, het moet wel UTF-8 zijn: "Content-Type: text/plain; charset=UTF-8" :P
En bedoel je nou dat ik 2 filters op 1 inputstream moet gaan hangen? Weet niet zeker, maar volgens mij werkte dat niet echt lekker. De bufferedreader trok em voor mijn neus leeg ofzo. Maar daar kan ik ook helemaal naast zitten =)
Je kan uit die bytearray gewoon lezen met je BufferReader.
edit:

Okay! Ik heb het min of meer :P
Bij het ontvangen controleer ik gewoon of ie tussen die bepaalde waardes ligt(zie 2e post hierboven... en bij versturen:
code:
1
2
3
4
5
6
7
int numBytes = -2;
String s = "één";
try {
     numBytes = s.getBytes("UTF-8").length;
} catch (UnsupportedEncodingException e) {}

System.out.println(numBytes );

Tadaa!!! :D 8)
Tja, ik zou je aanraden gewoon de standaard Java input en output stream te gebruiken, en niet zelf met dingen te gaan klooien. Bovendien converteer je je Strings maar 1 keer naar UTF-8 en niet 2 keer zoals jij het nu wilt doen. Maar ja als je naar mij gaat luisteren werk je straks met jabber ipv MSN :P

Opera OpenOffice.org Jabber Psi jabber://llama@mordax.com

Pagina: 1