2010-06-22 9 views
5

Napisałem następującą metodę, aby sprawdzić, czy określony plik zawiera tylko znaki tekstowe ASCII lub dodatkowo kontrolować znaki. Czy możesz rzucić okiem na ten kod, zasugerować ulepszenia i wskazać niedopatrzenia?Jak sprawdzić, czy plik jest binarny?

Logika jest następująca: „Jeśli pierwsze 500 bajtów pliku zawiera 5 lub więcej znaków sterujących - raport jako plik binarny”

dziękuję.

public boolean isAsciiText(String fileName) throws IOException { 

    InputStream in = new FileInputStream(fileName); 
    byte[] bytes = new byte[500]; 

    in.read(bytes, 0, bytes.length); 
    int x = 0; 
    short bin = 0; 

    for (byte thisByte : bytes) { 
     char it = (char) thisByte; 
     if (!Character.isWhitespace(it) && Character.isISOControl(it)) { 

      bin++; 
     } 
     if (bin >= 5) { 
      return false; 
     } 
     x++; 
    } 
    in.close(); 
    return true; 
} 

Odpowiedz

3

Ponieważ nazywasz tę klasę "isASCIIText", wiesz dokładnie, czego szukasz. Innymi słowy, nie jest to "isTextInCurrentLocaleEncoding". W ten sposób można być bardziej dokładne z:

if (thisByte < 32 || thisByte > 127) bin++; 

edytować, długi czas później — to wskazano w komentarzu, że ta prosta kontrola będzie wyzwalane przez plik tekstowy, który rozpoczął się z wieloma nowymi liniami. Prawdopodobnie lepiej będzie użyć tabeli z bajtami "ok" i zawierać znaki drukowalne (w tym powrót karetki, znak nowej linii i kartę, a także ewentualnie plik danych, chociaż nie sądzę, że używa ich wiele nowoczesnych dokumentów), a następnie sprawdzić stół.

+0

To tragedia, że ​​ta jest oznaczona jako poprawną odpowiedź, gdy ten algorytm będzie sklasyfikować plik zawierający „to \ r \ nis \ r \ nTylko \ r \ ntext” jako binarny. – Ingo

+1

@Ingo true; lepiej sprawdzić proporcje znaków kontrolnych do nie-kontroli, a także sprawdzić przypadki specjalne, takie jak znaki kontrolne wspólne dla tekstu. Byłem taki młody, kiedy wpisałem tę odpowiedź :) – Pointy

3

x nie wydaje się nic.

Co się stanie, jeśli plik ma mniej niż 500 bajtów?

Niektóre pliki binarne mają sytuację, w której możesz mieć nagłówek dla pierwszych N bajtów pliku, który zawiera pewne dane przydatne dla aplikacji, ale biblioteka, której dotyczy plik binarny, nie dba o to. Możesz łatwo mieć 500+ bajtów ASCII w preambule, jak to następuje, a następnie dane binarne w następującym gigabajtach.

powinien obsługiwać wyjątek, jeśli plik nie może zostać otwarty lub czytać, itp

1

Pierwszą rzeczą, jaką zauważyłem - niezwiązane z rzeczywistą pytanie, ale powinno być zamykając swój strumień wejściowy w finally bloku w celu zapewnienia zawsze jest zrobione. Zwykle obsługuje to tylko wyjątki, ale w twoim przypadku nawet nie zamkniesz strumieni plików po zwrocie false.

Oprócz tego, dlaczego porównanie ze znakami kontrolnymi ISO? To nie jest plik "binarny", to "plik zawierający 5 lub więcej znaków kontrolnych". Lepszym sposobem podejścia do sytuacji, w mojej opinii, byłoby odwrócenie kontroli - zamiast tego należy napisać funkcję isAsciiText, która zapewnia, że ​​wszystkie znaki w pliku (lub w pierwszych 500 bajtach, jeśli sobie tego życzysz) są w zbiorze bajtów które są znane dobre.

Teoretycznie sprawdzanie tylko pierwszych kilkuset bajtów pliku może spowodować problemy, jeśli jest to plik złożony (np. Tekst z osadzonymi obrazkami), ale w praktyce podejrzewam, że każdy taki plik będzie miał binarne dane nagłówka na starcie, więc prawdopodobnie jesteś OK.

0
  1. Ignorujesz to, co read() zwraca, a co, jeśli pliki są krótsze niż 500 bajtów?
  2. Po zwrocie false nie zamyka się pliku.
  3. Podczas konwersji bajtu na znak, zakładasz, że twój plik jest 7-bitowym ASCII.
0

Nie działałoby to z pakietami instalacyjnymi jdk dla systemów Linux i Solaris.mają początek skryptu powłoki, a następnie blob danych bi.

dlaczego nie sprawdzić typ MIME za pomocą biblioteki jak jMimeMagic (http://http://sourceforge.net/projects/jmimemagic/) i deside na podstawie typu MIME, jak obsługiwać plik.

3
  1. zawodzi źle, jeśli rozmiar pliku jest mniejszy niż 500 bajtów

  2. Linia char it = (char) thisByte; jest pojęciowo wątpliwe, miesza bajtów i znaków pojęć, tj. zakłada niejawnie, że kodowanie jest jednobajtowe = jeden znak (nie dotyczy kodowania Unicode). W szczególności nie powiedzie się, jeśli plik jest kodowany w UTF-16.

  3. Powrót w pętli (lekko zła praktyka IMO) zapomina zamknąć plik.