Visualizzazione dei risultati da 1 a 4 su 4

Discussione: Utf-16

  1. #1
    Utente di HTML.it L'avatar di skill83
    Registrato dal
    Mar 2002
    Messaggi
    2,024

    Utf-16

    Salve ragazzi ho bisogno di leggere e scrivere un file in utf-16 ma ho trovato info solo a riguardo utf-8 e sono arrivato alla conclusione che non c'è modo (se c'è ditemelo per favore)

    esiste un escamotage per ottenere lo stesso risultato???


    grazie a presto

  2. #2

    Re: Utf-16

    Originariamente inviato da skill83
    Salve ragazzi ho bisogno di leggere e scrivere un file in utf-16 ma ho trovato info solo a riguardo utf-8 e sono arrivato alla conclusione che non c'è modo (se c'è ditemelo per favore)

    esiste un escamotage per ottenere lo stesso risultato???


    grazie a presto
    http://it.wikipedia.org/wiki/UTF-16

    UTF-16 ha la stessa codifica dell'unicode se non erro

    Dai un occhiata anche qui

    http://it.wikipedia.org/wiki/UTF-16

    Diciamo che in generale ti basterebbe leggere i 2/4 byte dell'UTF-16 e ricostruire i byte (da 1 a 6) dell'UTF-8 e poi passare il tutto a utf8_decode per leggerli

    oppure, molto più semplicemente, utilizzi le funzioni di mb_string

  3. #3
    PS: ieri sera poi non avevo che fare e mi sono messo a scrivere un convertitore

    è quasi finito, mi interpreta corettamente le sequenze UTF-16 che corrispondono a quelle ad 1 byte, 2 byte e 3 byte di UTF-8.

    Per la sequenza da 4 byte UTF-16 in realtà non ho cosa testarci su :\

  4. #4
    Ho finito di sistemare il tutto, la funzione che ti posto vuole in ingresso un contenuto UTF-16 e ti butta fuori un contenuto UTF-8

    Non supporta il formato BIG ENDIAN cosa che verifica da solo se c'è il BOM ... ovviamente se gli viene passato il BOM se ne accorge e lo salta

    codice:
    function Utf16ToUtf8($Utf16Sequence, $Offset = 0, $Length = -1)
    {
    	// Verifica se la tabella ascii delle conversioni è stata già inizializzata
    	if (isset($GLOBALS['__AsciiTableCHR']) === false)
    	{
    		$GLOBALS['__AsciiTableCHR'] = array();
    		$GLOBALS['__AsciiTableORD'] = array();
    		for($i = 0; $i < 256; $i++)
    		{
    			$char = chr($i);
    			$GLOBALS['__AsciiTableCHR'][$char] = $i;
    			$GLOBALS['__AsciiTableORD'][$i] = $char;
    		}
    	}
    
    	// Inizializza la sequenza di uscita
    	$utf8Sequence = '';
    
    	// Acquisisce la lunghezza della sequenza
    	$utf16SequenceLength = strlen($Utf16Sequence);
    	
    	// Inizializza l'indice dei byte
    	$byteIndex = 0;
    	
    	// Verifica se è presente il BOM in formato Little Endian
    	if ($Utf16Sequence{0} == chr(0xFF) && $Utf16Sequence{1} == chr(0xFE))
    	{
    		$byteIndex = 2;
    	}
    	
    	// Verifica se è presente il BOM in formato Big Endian
    	else if ($Utf16Sequence{0} == chr(0xFE) && $Utf16Sequence{1} == chr(0xFF))
    	{
    		die('Big Endian encoding not supported');
    	}
    	
    	// Inizializza i counter
    	$offsetCounter = 0;
    	$lengthCounter = 0;
    	
    	// Cicla la sequenza
    	for(; $byteIndex < $utf16SequenceLength; $byteIndex += 2)
    	{
    		// Acquisisce il valore numerico del primo e del secondo byte
    		$firstByte = $GLOBALS['__AsciiTableCHR'][$Utf16Sequence[$byteIndex]];
    		$secondByte = $GLOBALS['__AsciiTableCHR'][$Utf16Sequence[$byteIndex + 1]];
    		
    		// Verifica se il byte corrente inizia con 110110xx
    		if (($firstByte & 0xD8) == 0xD8)
    		{
    			// Acquisisce il terzo byte
    			$thirdByte = $GLOBALS['__AsciiTableCHR'][$Utf16Sequence[$byteIndex + 2]];
    			
    			// Verifica se la maschera DC da un risultato positivo
    			if (($thirdByte & 0xDC) == 0xDC)
    			{
    				die('Unsupported four bytes ssequence starting at offset ' . $byteIndex . '!');
    				
    				/**
    				 * UNSUPPORTED!
    				 * 				 
    
    				// Legge il quarto byte
    				$fourthByte = $GLOBALS['__AsciiTableCHR'][$Utf16Sequence[$byteIndex + 3]];
    
    				// Costruisce la sequenza UTF8
    				$utf8Sequence .= chr(0xF0 + ($firstByte & 0x03));
    				$utf8Sequence .= chr(0x80 + ($secondByte & 0x7C));
    				$utf8Sequence .= chr(0x80 + (($secondByte & 0x03) << 4) + (($thirdByte & 0x03) << 2) + 
    					$fourthByte & 0xC0));
    				$utf8Sequence .= chr(0x80 + ($fourthByte & 0xFC));
    				
    				// Dopo aver effettuato le operazioni fa un salto aggiuntivo di 2 byte
    				// nella sequenza
    				$byteIndex += 2;
    				
    				// Passa alla sequenza successiva
    				continue;
    				
    				 *
    				 **/
    			} 
    		}
    
    		// Incrementa il counter dell'offset
    		$offsetCounter++;
    		
    		// Verifica se deve leggere il carattere
    		if ($offsetCounter < $Offset)
    		{
    			// Passa al blocco successivo
    			continue;
    		}
    		
    		// Se l'esecuzione arriva qui la sequenza è formata solo da 2 byte quindi verifica
    		// quale range è quello corretto per la codifica, in questo caso è il range ascii
    		// (ovvero 0xxxxxxx)
    		if ($secondByte == 0 && ($firstByte & 0x80) == 0)
    		{
    			$utf8Sequence .= $GLOBALS['__AsciiTableORD'][$firstByte & 0x7F];
    		}
    		
    		// Verifica se questo è il range di caratteri che va da 0x000080 a 0x0007FF, ovvero se
    		// i primi 5 bit del primo byte sono pari a zero (110xxxxx 10xxxxxx)
    		else if (($secondByte & 0xF8) == 0)
    		{
    			$utf8Sequence .= $GLOBALS['__AsciiTableORD'][0xC0 + (($secondByte & 0x07) << 2) +
    				(($firstByte & 0xC0) >> 6)];
    			$utf8Sequence .= $GLOBALS['__AsciiTableORD'][0x80 + ($firstByte & 0x3F)];
    		}
    		
    		// Questo è il range di caratteri che va da 0x000800 - 0x00FFFF (1110xxxx 10xxxxxx 10xxxxxx)
    		else
    		{
    			$utf8Sequence .= $GLOBALS['__AsciiTableORD'][0xE0 + (($secondByte & 0xF0) >> 4)];
    			$utf8Sequence .= $GLOBALS['__AsciiTableORD'][0x80 + (($secondByte & 0x0F) << 2) +
    				(($firstByte & 0xC0) >> 6)];
    			$utf8Sequence .= $GLOBALS['__AsciiTableORD'][0x80 + ($firstByte & 0x3F)]; 
    		}
    		
    		// Incrementa il counter della lunghezza
    		$lengthCounter++;
    		
    		// Verifica se ha letto tutti i caratteri che dovevano essere letti
    		if ($Length == $lengthCounter)
    		{
    			// Interrompe il ciclo di analisi
    			break;
    		}
    	}
    	
    	// Restituisce la sequenza
    	return $utf8Sequence;
    }
    Non so a livello di performance com'è messa, ho fatto dei test su 100kb di dati e ci sta circa 0.1s (51870 caratteri da convertire per la precisione con gli ultimi test che ho fatto)

    purtroppo fa un sacco di lavoro inutile perché php non mi fa applicare le maschere ad i singoli caratteri pur essendo per lui un singolo byte in memoria e quindi prima mi tocca convertirli in numero

    Se si accelera quell'operazione e l'operazione inversa (ad esempio tramite una tabella) sicuramente ci sarà un recupero di velocità

    UPDATE
    Ho variato il codice in modo da fargli creare 2 tabelle di conversione da indice a carattere e viceversa ... cosi il tempo di esecuzione è sceso a 0.08 ... non c'è stato un cambiamento abbissale però se la conversione deve essere eseguita più volte ora è più veloce.

    In aggiunta ho anche implementato il codice necessario per iniziare a leggere da un dato carattere ed il codice necessario per leggere N caratteri

    mmm per sapere quanti caratteri sono presenti indicativamente puoi fare la lunghezza del file / 2 ... nel caso che è presente il BOM prima di dividere devi togliere 2 byte. Nel caso in qui ci sono sequenze da 4 byte ti sballa il calcolo

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.