2009-10-04 11 views
7

Korzystam z interfejsu API Zemanta, który akceptuje do 8 KB tekstu na połączenie. Wyodrębniam tekst do wysłania do Zemanta ze stron internetowych przy użyciu JavaScript, więc szukam funkcji, która obetnie mój tekst dokładnie o 8 KB.Używanie JavaScript do obcinania tekstu do określonego rozmiaru (8 KB)

Zemanta powinien sam wykonać to obcięcie (tj. Jeśli wyślesz większy ciąg), ale muszę trochę przesunąć ten tekst, zanim wykonam wywołanie API, więc chcę zachować ładowność tak małą jak możliwy.

Czy można bezpiecznie założyć, że 8 KB tekstu ma 8192 znaków i odpowiednio przyciąć? (1 bajt na znak, 1024 znaki na KB, 8 KB = 8 192 bajty/znaki) Czy jest to niedokładne lub prawdziwe tylko w niektórych okolicznościach?

Czy istnieje bardziej elegancki sposób obcięcia ciągu na podstawie jego rzeczywistego rozmiaru pliku?

+0

Możesz chcieć sprawdzić, czy tekst, z którym masz do czynienia, ma określone kodowanie, np. UTF-8, ASCII itp? Jeśli masz pewność, że tekst zawiera tylko znaki jednobajtowe, obcięcie będzie prostsze. Zyskasz trochę elastyczności. Jeśli chodzi o to, czy Zemanta traktuje 8 KB jako 8192 bajty lub 8000 bajtów, dlaczego nie przetestujesz go sam? –

+0

Dzięki, o.k.w.Myślę, że Dominic ma rację, że ten tekst (prawdopodobnie UTF-8) może potencjalnie zająć wiele bajtów na znak, więc pomiary na podstawie liczby znaków nie będą możliwe. – Bungle

Odpowiedz

9

Jeśli używasz kodowania jednobajtowego, tak, 8192 znaki = 8192 bajtów. Jeśli używasz UTF-16, 8192 znaki (*) = 4096 bajtów.

(właściwie 8192 code-punkty, co jest nieco inna rzecz w obliczu surogatów, ale niech nie martwić, że ponieważ JavaScript nie robi.)

Jeśli używasz UTF-8, nie ma szybkie trik można wykorzystać do realizacji UTF-8 koder/dekoder w JS z minimalnym kodu:

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

teraz można obciąć z:

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); 
    } 
} 

(powodem try-c atch jest, że jeśli skasujesz bajty w środku wielobajtowej sekwencji znaków, otrzymasz niepoprawny strumień UTF-8, a decodeURIComponent złoży skargę.)

Jeśli jest to inne kodowanie wielobajtowe, takie jak Shift-JIS lub Big5, jesteś sam.

+1

To jest dokładnie to, czego szukałem - działa jak urok! Dzięki, Bobo. Po prostu całkiem spostrzeżenie dla potomności - jestem trochę gęsty, więc zajęło mi kilka minut, aby zdać sobie sprawę, że zmienne "unicodecharacters" i "utf8bytes" w twoich funkcjach są tylko dla wyjaśnienia i powinny faktycznie pasować do argumentów do pracy (tj. oba powinny zostać zastąpione przez "s" w dwóch krótszych funkcjach). Dzięki jeszcze raz! – Bungle

+1

Whoops! Niebezpieczeństwa związane z cięciem i wklejaniem. Ta za połów! – bobince

2

Nie można założyć, że 8 KB tekstu ma 8192 znaki, ponieważ w niektórych kodowaniach znaków każda postać zajmuje multiple bytes.

Jeśli czytasz dane z plików, czy nie możesz pobrać pliku? Lub przeczytać w fragmentach 8KB?

+0

Dzięki, Dominic - Zbieram ten tekst z dokumentu za pomocą metody JavaScript .innerText() zamiast pliku .txt lub czegoś takiego, więc nie jestem pewien, czy istnieje sposób na określenie "daj mi 8 KB dane "- to jest idealnie to, czego szukam. – Bungle

1

Jak mówi Dominic, kodowanie znaków jest problemem - jednak jeśli potrafisz albo naprawdę upewnij się, że poradzisz sobie tylko z 8-bitowymi znakami (mało prawdopodobne, ale możliwe) lub zakładasz 16-bitowe znaki i ogranicz się do połowy dostępne miejsce, czyli 4096 znaków, wtedy możesz spróbować.

To zły pomysł, aby polegać na JS, ponieważ można go w prosty sposób zmodyfikować lub zignorować, a na przykład w przypadku komplikacji znaków escape i kodowania. Lepiej używać JS jako filtra pierwszej szansy i używać dowolnego dostępnego języka po stronie serwera (który również otworzy kompresję).

+0

Dzięki, annakata - wygląda na to, że funkcje Bobka będą działać w moim przypadku. Zemanta powinna po prostu odciąć dowolny tekst ponad limit 8 KB, więc jestem mniej zaniepokojony tym, co ostatecznie dostaje się do ich API (oczywiście oprócz oszczędzania przepustowości), ponieważ maksymalne zyski wydajności w tym przypadku będą ograniczać się do co najmniej około 8 KB po stronie klienta. – Bungle

Powiązane problemy