2011-07-02 21 views
6

W moim programie użytkownik może załadować plik z łączami (to jest webcrawler), ale muszę sprawdzić, czy plik wybrany przez użytkownika to zwykły tekst lub coś innego (dozwolony jest tylko zwykły tekst).Jak sprawdzić, czy plik jest zwykłym tekstem?

Jest to możliwe? Jeśli jest to przydatne, używam JFileChooser do otwarcia pliku.

EDIT:

Czego oczekuje od użytkownika: pliku tekstowego zawierającego adresy URL.

Co chcę uniknąć: użytkownik wczytuje plik MP3 lub dokument z MS Word (przykłady).

Odpowiedz

5

Plik to tylko seria bajtów i bez dalszych informacji nie można stwierdzić, czy te bajty mają być kodowane w kodowaniu ciągów znaków (np. ASCII lub UTF-8 lub ANSI-coś) lub czymś innym . Będziesz musiał odwołać się do heurystyki, na przykład:

  • Spróbuj przeanalizować plik w wielu znanych kodowaniach i sprawdź, czy przetwarzanie zakończyło się pomyślnie. Jeśli tak, prawdopodobnie masz plik tekstowy.
  • Jeśli spodziewasz się plików tekstowych tylko w zachodnich językach, możesz założyć, że większość znaków znajduje się w zakresie ASCII (0..127), a dokładniej (33..127) plus białe znaki (tabulacja, znak nowej linii, karetka return, space). Zliczaj wystąpienia każdej odrębnej wartości bajtu, a jeśli przytłaczająca część twojego dokumentu znajduje się w zestawie "typowych zachodnich znaków", zwykle można bezpiecznie założyć, że jest to plik tekstowy.
  • Rozszerzenie poprzedniego podejścia; wypróbuj wystarczająco dużą ilość tekstu w językach, których się spodziewasz, i zbuduj profil częstotliwości postaci. Aby sprawdzić swój plik, porównaj profil częstotliwościowy pliku z danymi testowymi i sprawdź, czy jest wystarczająco blisko.

Ale tutaj jest inne rozwiązanie: Traktuj wszystko, co otrzymasz jako tekst, stosując niezbędne transformacje tam, gdzie jest to potrzebne (np. Kodowanie HTML podczas wysyłania do przeglądarki internetowej). Dopóki uniemożliwisz interpretację pliku jako danych binarnych (takich jak dwukrotne kliknięcie pliku przez użytkownika), najgorsze, co możesz wytworzyć, są bzdury.

2

Tekst jest również formą danych binarnych.

Przypuszczam, że to, co chcesz sprawdzić, to czy są jakieś znaki na wejściu, które są < 32. Jeśli możesz bezpiecznie założyć, że twój tekst jest kodowany wielobajtowo, możesz po prostu zeskanować cały plik i przerwać jeśli trafisz bajt w zakresie [0, 32] (z wyłączeniem 9, 10, 13 i cokolwiek innego możesz poza "tekstem" - lub najgorszym przypadku tylko sprawdź bajty null [dzięki, tdammers!]). Jeśli możesz oczekiwać, że otrzymasz zakodowany kod UTF-16 lub UTF-32, będziesz musiał pracować ciężej.

+0

Zakładka, znak nowej linii i powrót karetki <32. – tdammers

+0

@tdammers: Whoops, good catch. OK, wyklucz te z meczu! A co z wierszami? :-) –

+0

Prawdopodobnie sprawdziłbym, czy plik jest UTF-8, zakładając, że jest to tekst, jeśli jest poprawny UTF-8 (prawdopodobnie wykluczając współrzędne kodowe <32, z wyjątkiem tabulatora, znaku nowej linii i znaku powrotu karetki, a także 127). – MRAB

0

Należy utworzyć filtr, który obejrzy opis pliku i sprawdzi tekst.

1

Jeśli nie chcesz zgadywać przez file extension, możesz przeczytać pierwszą część pliku. Ale następnym problemem będzie kodowanie znaków. Używając później i później), zawiń za pomocą InputStreamReader z kodowaniem "ISO-8859-1" i policz lekturę odczytaną za pomocą Character.isLetterOrDigit() lub Character.isWhitespace(), aby uzyskać stosunek typowej zawartości tekstowej. Myślę, że stosunek powinien wynosić ponad 80% dla pliku tekstowego.

Można również wypróbować inne kodowanie, np. UTF-8, ale mogą wystąpić problemy z nieprawidłowymi znakami, gdy nie jest to UTF-8.

+0

Mogę łatwo zmienić nazwę rozszerzenia obrazu na ".TXT" i spróbować załadować go do aplikacji, która próbuje otworzyć plik 'text' i spowodować awarię. – Si8

+0

@ SiKni8: To nie było pytanie, a dobra aplikacja nie zawiedzie się podczas otwierania pliku binarnego! –

1

Można również sprawdzić, czy początkowe bajty są BOM, który powinien wskazywać plik w formacie UTF:

- UTF-8  => 0xEF, 0xBB, 0xBF 
- UTF-16 BE => 0xFE, 0xFF 
- UTF-16 LE => 0xFF, 0xFE 

Rossum

0

można wywołać polecenie powłoki file -i ${filename} z Java i sprawdzić wyjście, aby zobaczyć, czy zawiera coś w rodzaju charset=binary. Jeśli tak, to jest to plik binarny. W przeciwnym razie jest to plik tekstowy.

Możesz grać z file w powłoce na różnych plikach i zapoznać się z nią. W Groovy będę pisać coś takiego

'file -i ${path/to/myfile}'.execute().getText().contains('charset=binary')

w Javie można również nazwać poleceń powłoki. Proszę zapoznać się z this.

Powiązane problemy