2009-10-04 9 views
7

Utilizzo l'API Zemanta, che accetta fino a 8 KB di testo per chiamata. Sto estraendo il testo da inviare a Zemanta dalle pagine Web utilizzando JavaScript, quindi sto cercando una funzione che troncherà il mio testo esattamente a 8 KB.Utilizzo di JavaScript per troncare il testo a una determinata dimensione (8 KB)

Zemanta dovrebbe eseguire questo troncamento da solo (cioè, se si invia una stringa più grande), ma ho bisogno di spostare questo testo un po 'prima di effettuare la chiamata API, quindi voglio mantenere il carico utile piccolo come possibile.

È sicuro assumere che 8 KB di testo siano 8.192 caratteri e troncare di conseguenza? (1 byte per carattere, 1.024 caratteri per KB, 8 KB = 8,192 byte/caratteri) Oppure, è impreciso o vero solo in determinate circostanze?

Esiste un modo più elegante per troncare una stringa in base alle dimensioni effettive del file?

+0

Si potrebbe voler controllare se il testo di cui si ha a che fare è di certa codifica, ad es. UTF-8, ASCII ecc.? Se si è certi che il testo contenga solo caratteri a byte singolo, il troncamento sarà più semplice. Scambieresti un po 'di flessibilità. Per quanto riguarda il fatto che Zemanta tratti 8KB come 8192 byte o 8000 byte, perché non provi tu stesso? –

+0

Grazie, o.k.w.Penso che Dominic abbia ragione nel dire che questo testo (probabilmente UTF-8) prenderà potenzialmente più byte per carattere, quindi la misurazione su base di quantità di caratteri non sarà possibile. – Bungle

risposta

9

Se si utilizza una codifica a byte singolo, sì, 8192 caratteri = 8192 byte. Se si utilizza UTF-16, 8192 caratteri (*) = 4096 byte.

(In realtà 8192 code-punti, che è una cosa un po 'diversa a fronte di surrogati, ma cerchiamo di non preoccuparsi di questo perché JavaScript non lo fa.)

Se si utilizza UTF-8, c'è un trucco veloce è possibile utilizzare per implementare un UTF-8 encoder/decoder in JS con codice minimo:

function toBytesUTF8(chars) { 
    return unescape(encodeURIComponent(chars)); 
} 
function fromBytesUTF8(bytes) { 
    return decodeURIComponent(escape(bytes)); 
} 

Ora è possibile troncare con:

function truncateByBytesUTF8(chars, n) { 
    var bytes= toBytesUTF8(chars).substring(0, n); 
    while (true) { 
     try { 
      return fromBytesUTF8(bytes); 
     } catch(e) {}; 
     bytes= bytes.substring(0, bytes.length-1); 
    } 
} 

(il motivo per il try-c è possibile che se tronchi i byte nel mezzo di una sequenza di caratteri multibyte otterrai un flusso UTF-8 non valido e decodeURIComponent si lamenterà.)

Se si tratta di un'altra codifica multibyte come Shift-JIS o Big5, sei da solo.

+1

Questo è esattamente quello che stavo cercando - funziona come un fascino! Grazie, Bobince. Solo una nota abbastanza per i posteri - Sono un po 'fitto quindi mi ci sono voluti alcuni minuti per rendermi conto che le variabili "unicodecharacters" e "utf8bytes" nelle tue funzioni sono solo a scopo di spiegazione, e dovrebbero effettivamente corrispondere agli argomenti per funzionare (cioè, entrambi dovrebbero essere sostituiti con "s" nelle due funzioni più corte). Grazie ancora! – Bungle

+1

Whoops! I pericoli del taglia-e-incolla, lì. Ta per il pescato! – bobince

2

No, non è sicuro assumere che 8 KB di testo siano 8192 caratteri, poiché in alcune codifiche di caratteri, ogni carattere occupa multiple bytes.

Se stai leggendo i dati dai file, non puoi semplicemente prendere il file? O leggerlo in blocchi di 8KB?

+0

Grazie, Dominic - Sto raccogliendo questo testo da un documento utilizzando il metodo .innerText() di JavaScript (piuttosto che un file .txt o qualcosa del genere), quindi non sono sicuro che ci sia un modo per specificare "dammi 8 KB di dati "- è idealmente quello che sto cercando, però. – Bungle

1

Come dice Dominic, la codifica dei caratteri è il problema - se è possibile veramente garantire che avrete a che fare solo con i caratteri a 8 bit (improbabile, ma possibile) o assumere caratteri a 16 bit ea limitarsi a metà lo spazio disponibile, vale a dire 4096 caratteri, quindi è possibile provare questo.

È una cattiva idea affidarsi a JS per questo, anche perché può essere banalmente modificato o ignorato e si hanno complicazioni di escape char e codifica da affrontare ad esempio. È meglio usare JS come filtro di prima scelta e utilizzare qualsiasi lingua lato server disponibile (che aprirà anche la compressione).

+0

Grazie, annakata: sembra che le funzioni di bobince funzioneranno nel mio caso. Zemanta dovrebbe in realtà tagliare qualsiasi testo oltre il limite di 8 KB, quindi sono meno preoccupato di ciò che alla fine raggiungerà la loro API (a parte conservare la larghezza di banda, ovviamente), poiché il massimo guadagno di prestazioni in questo caso si limiterà a almeno circa 8 KB sul lato client. – Bungle

Problemi correlati