2009-10-04 17 views
7

Uso la API Zemanta, que acepta hasta 8 KB de texto por llamada. Estoy extrayendo el texto para enviarlo a Zemanta desde páginas web usando JavaScript, así que estoy buscando una función que trunque mi texto exactamente a 8 KB.Uso de JavaScript para truncar texto a un tamaño determinado (8 KB)

Zemanta debería hacer este truncamiento por sí mismo (es decir, si le envía una cadena más grande), pero necesito enviar este texto un poco antes de hacer la llamada API, así que quiero mantener la carga tan pequeña como posible.

¿Es seguro asumir que 8 KB de texto son 8.192 caracteres, y truncar en consecuencia? (1 byte por carácter, 1.024 caracteres por KB, 8 KB = 8.192 bytes/caracteres) O, ¿es eso incorrecto o solo cierto dadas ciertas circunstancias?

¿Hay una forma más elegante de truncar una cadena en función de su tamaño de archivo real?

+0

Es posible que desee comprobar si el texto que está tratando tiene cierta codificación, p. UTF-8, ASCII, etc. Si está seguro de que el texto contiene solo caracteres de un solo byte, el truncamiento será más sencillo. Cambiarás algo de flexibilidad. En cuanto a si Zemanta trata 8 KB como 8192 bytes u 8000 bytes, ¿por qué no lo prueba usted mismo? –

+0

Gracias, o.k.w.Creo que Dominic tiene razón en que este texto (probablemente UTF-8) potencialmente ocupará múltiples bytes por carácter, por lo que no será posible medir en función de la cantidad de caracteres. – Bungle

Respuesta

9

Si está utilizando una codificación de un solo byte, sí, 8192 caracteres = 8192 bytes. Si está utilizando UTF-16, 8192 caracteres (*) = 4096 bytes.

(en realidad 8192 puntos de código, que es una cosa un poco diferente en la cara de los sustitutos, pero no hay que preocuparse por eso, porque JavaScript no lo hace.)

Si está utilizando UTF-8, hay una truco rápido que puede utilizar para implementar un UTF-8 codificador/decodificador de JS con el código mínimo:

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

ya se puede truncar 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); 
    } 
} 

(la razón para el try-c Por ejemplo, si truncas los bytes en el medio de una secuencia de caracteres multibyte obtendrás una secuencia UTF-8 inválida y decodeURIComponent se quejará).

Si se trata de otra codificación multibyte como Shift-JIS o Big5, estás sólo en esto.

+1

Esto es exactamente lo que estaba buscando, ¡funciona como un encanto! Gracias, Bobince. Una nota bastante buena para la posteridad: soy un poco denso, así que me tomó unos minutos darme cuenta de que las variables "unicodecharacters" y "utf8bytes" en sus funciones son solo por razones de explicación, y deberían coincidir con los argumentos para trabajar (es decir, ambos deben reemplazarse por "s" en las dos funciones más cortas). ¡Gracias de nuevo! – Bungle

+1

¡Vaya! Los peligros de cortar y pegar, allí. Ta por la captura! – bobince

2

No, no es seguro suponer que 8 KB de texto son 8192 caracteres, ya que en algunas codificaciones de caracteres, cada carácter ocupa multiple bytes.

Si está leyendo los datos de los archivos, ¿no puede simplemente tomar el tamaño del archivo? ¿O leerlo en pedazos de 8 KB?

+0

Gracias, Dominic: estoy recopilando este texto de un documento utilizando el método de .innerText() de JavaScript (en lugar de un archivo .txt o algo así), así que no estoy seguro de que haya una forma de especificar "dame 8 KB de datos "- eso es idealmente lo que estoy buscando, sin embargo. – Bungle

1

Como dice Dominic, la codificación de caracteres es el problema - sin embargo, si usted puede realmente asegurarse de que sólo va a lidiar con caracteres de 8 bits (poco probable pero posible) o asumir caracteres de 16 bits y se limite a la mitad el espacio disponible, es decir, 4096 caracteres, entonces podrías intentarlo.

Aunque es una mala idea confiar en JS porque se puede modificar o ignorar de manera trivial y tiene complicaciones con los caracteres de escape y la codificación, por ejemplo. Es mejor utilizar JS como un filtro de primera oportunidad y usar el lenguaje del lado del servidor que tenga disponible (que también abrirá la compresión).

+0

Gracias, annakata - parece que las funciones de Bobince funcionarán en mi caso. Zemanta debería simplemente cortar cualquier texto por encima del límite de 8 KB, así que estoy menos preocupado por lo que eventualmente llegue a su API (aparte de conservar el ancho de banda, por supuesto), ya que las máximas ganancias de rendimiento en este caso limitarán al menos aproximadamente 8 KB en el lado del cliente. – Bungle

Cuestiones relacionadas