001    package de.hska.java.aufgaben.ausdruecke;
002    
003    /**
004     * Enthält eine main-Methode, die ein char-Wert (16 Bit Unicode)
005     * in den entsprechenden UTF-8 int-Wert konvertiert.
006     * <p>
007     *   Hier geht es zur <a title="Zum Aufgabentext dieser Java-Übungsaufgabe"
008     *   href="http://www.home.hs-karlsruhe.de/~pach0003/informatik_1/aufgaben/datentypen.html#unicode_nach_utf8">Beschreibung dieser Java-Aufgabe</a>
009     * </p>
010     * 
011     * @author Christian Pape
012     */
013    public class UnicodeNachUTF8 {
014    
015        /**
016         * Konvertiert ein char nach UTF-8 mit Hilfe eines einzigen
017         * Ausdrucks. Man beachte, dass dieser nicht wirklich lesbar ist.
018         * Insbesondere die Kommentare sind notwendig, damit ersichtlich
019         * wird, was der Ausdruck überhaupt macht.
020         * In der Praxis sollten besser die drei Fälle mit if-else abgefragt werden,
021         * damit der sequentieller Berechnungsablauf erkennbar ist.
022         * Ebenso könnten Teilergebnisse in Variablen zwischengespeichert werden.
023         */
024        public static void main(String[] args) {
025            char c = 'ä';
026            int utf8 = 0;
027            
028            System.out.println(Integer.toBinaryString(c));
029            
030            utf8 = ( 0 == (c & 0xFF80) // höchstens ersten 7 Bits gesetzt
031                     ? c // c ist selbst der Unicode 
032                     :  (  0 == (c & 0xF800 ) // ersten 11 Bits gesetzt
033                        ? (  // Bits für das 1. Byte bestimmen
034                             (((c >> 6) & 0x001F) << 8 
035                              | 0xC000) ) // führende binäre 110
036                               // 2. Byte hat ersten 6 Bits ohne die anderen
037                              | (c & 0x003F) 
038                              | 0x0080 // führende binäre 10
039                        : ( // 16 Bits gesetzt
040                            // 1. Byte 
041                              (c >> 12 & 0x0F | 0xE0) << 16
042                            | // 2. und 3. analog wie oben
043                            (((c >> 6) & 0x003F) << 8  | 0x8000) ) 
044                               | (c & 0x003F) | 0x0080
045                            ) ) ;
046            
047            System.out.println(Integer.toBinaryString(utf8));
048            
049            // Besser so (nicht getestet)
050            if ( 0 == (c & 0xFF80) ) { // c hat höchstens 7 Bits
051                utf8 = c;
052            } else if ( 0 == (c & 0xF800 ) ) { // c hat höchstens 11 Bits
053                utf8 = (((c >> 6) & 0x001F) << 8 
054                        | 0xC000 ) // vorderen 5 Bits mit führendem binären 110
055                        |(c & 0x003F) 
056                        | 0x0080; // hinteren 6 Bits mit führendem binären 10                    
057            } else { // mindestens 12 Bits sind gesetzt
058                utf8 = (c >> 12 & 0x0F | 0xE0) << 12 // 1. Byte
059                        // 2. und 3. Byte analog wie oben 
060                        | (((c >> 6) & 0x003F) << 8  | 0x8000)
061                        | (c & 0x003F)
062                        | 0x0080;
063            }
064            
065            // Oder auch so (auch nicht getestet)
066            int  byte1 = 0,
067                 byte2 = 0, 
068                 byte3 = 0;
069            
070            if ( 0 == (c & 0xFF80) ) { // c hat höchstens 7 Bits
071                byte3 = c;
072            } else if ( 0 == (c & 0xF800 ) ) { // c hat höchstens 11 Bits
073                byte2  = ((c >> 6) & 0x001F) | 0xC0; 
074                byte3 =  (c & 0x003F) | 0x0080; // hinteren 6 Bits mit führendem binären 10
075                        
076            } else { // mindestens 12 Bits sind gesetzt
077                byte1 = (c >> 12 & 0x0F | 0xE0);
078                byte2 = (((c >> 6) & 0x003F) | 0x80);
079                byte3 = (c & 0x3F)| 0x80;
080            }
081            utf8 = (byte1 << 16) | (byte2 << 8) | byte3;
082        }
083    
084    }