2012-02-29 6 views
13

Mam dziwne zachowanie ze skanerem. Będzie działać z konkretnym zestawem plików, których używam, gdy używam konstruktora Scanner(FileInputStream), ale nie będzie to możliwe z konstruktorem Scanner(File).Java Scanner (plik) działa niewłaściwie, ale skaner (FIleInputStream) zawsze działa z tym samym plikiem

Przypadek 1: Scanner(File)

Scanner s = new Scanner(new File("file")); 
while(s.hasNextLine()) { 
    System.out.println(s.nextLine()); 
} 

Wynik: ma wyjścia

Przypadek 2: Scanner(FileInputStream)

Scanner s = new Scanner(new FileInputStream(new File("file"))); 
while(s.hasNextLine()) { 
    System.out.println(s.nextLine()); 
} 

Wynik: czy plik wyjścia zawartość do konsoli.

Plik wejściowy jest plikiem java zawierającym pojedynczą klasę.

I podwójne sprawdzone programowo (w Javie), że:

  • plik istnieje,
  • jest czytelny,
  • i ma niezerową rozmiar pliku.

Zazwyczaj Scanner(File) działa dla mnie w tym przypadku, nie jestem pewien, dlaczego nie teraz.

+0

Co plik zawiera? – Dan675

+0

A czy to jedyny kod, czy też dzieje się wokół tego coś innego? Ten fragment kodu wydaje się być niekompletny, ponieważ zachodzi co najmniej obsługa wyjątków. Czy możesz podać nam cały kod? – haylem

+0

Interesujące pytanie. Podaj swój aktualny kod i pastebin z plikiem. Co to jest wyjście 'charset.defaultCharset()' w twoim systemie? – Perception

Odpowiedz

7

hasNextLine() wzywa findWithinHorizon() co z kolei wywołuje findPatternInBuffer(), szukając mecz na wzór postaci linii terminatora zdefiniowany jako .*(\r\n|[\n\r\u2028\u2029\u0085])|.+$

Najdziwniejsze jest to, że z obu sposobów konstruowania Scanner (z FileInputStream lub poprzez File), findPatternInBuffer powroty dodatnie dopasowanie, jeśli plik zawiera (niezależnie od rozmiaru pliku) na przykład terminator linii 0x0A; ale w przypadku, gdy plik zawiera znak z ascii (tj.> = 7f), użycie FileInputStream zwróci wartość true, używając opcji File zwraca false.

Bardzo prosty przypadek testowy:

utworzyć plik zawierający tylko znak "a"

# hexedit file  
00000000 61 0A            a. 

# java Test.java 
using File: true 
using FileInputStream: true 

teraz edytować plik z HexEdit do:

# hexedit file 
00000000 61 0A 80            a.. 

# java Test.java 
using File: false 
using FileInputStream: true 

w kodzie testu java nie ma nic więcej niż to, o czym już w pytaniu:

import java.io.*; 
import java.lang.*; 
import java.util.*; 
public class Test { 
    public static void main(String[] args) { 
     try { 
       File file1 = new File("file"); 
       Scanner s1 = new Scanner(file1); 
       System.out.println("using File: "+s1.hasNextLine()); 
       File file2 = new File("file"); 
       Scanner s2 = new Scanner(new FileInputStream(file2)); 
       System.out.println("using FileInputStream: "+s2.hasNextLine()); 
     } catch (IOException e) { 
       e.printStackTrace(); 
     } 
    } 
} 

Okazuje się, że jest to problem z zestawem znaków. W faktach, zmieniając test:

Scanner s1 = new Scanner(file1, "latin1"); 

otrzymujemy:

# java Test 
using File: true 
using FileInputStream: true 
+0

Interesujące ... Kiedy patrzy się na contruktorów typu "skaner", wydaje się, że domyślnie przyjmują domyślny zestaw znaków, ale nie ma różnicy w czasie wykonywania, jak wskazujesz. użyty wewnętrznie może wymusić inny, jeden poziom głębszy? Zastanawiam się ... Czy spróbuję sprawdzić, kiedy dostanę szansę. – haylem

5

Od patrząc na Oracle/Sun JDK's 1.6.0_23 implementation of Scanner, konstruktor Scanner(File) wywołuje FileInputStream, który jest meant for raw binary data.

Wskazuje to na różnicę w technice buforowania i parsowania używanej podczas wywoływania jednego konstruktora lub innego, co bezpośrednio wpłynie na twój kod podczas rozmowy pod numerem hasNextLine().

Scanner(InputStream) wykorzystuje InputStreamReader podczas Scanner(File) wykorzystuje InputStream przekazany do ByteChannel (i zapewne czyta cały plik w jednym skoku, a tym samym pogłębianie kursor w danym przypadku).

+0

bardzo interesujące informacje, dziękuję za udostępnienie –

+2

Umowa na Java (plik) i Java (FileInputStream) czyta się tak samo, więc powinny one powodować takie samo zachowanie z punktu widzenia użytkownika API. Użyłem Java (File) wcześniej bez tego problemu. – kashiko

+0

Yanick: Dzięki, to interesujące pytanie. Ale wydaje się, że jest w tym coś więcej ... (Wciąż, rzeczy, które możesz wydobyć z kodu JDK ... Czasami, gdy zauważyłem, że istnieje wiele definicji 'ArrayList', na przykład (i nie, nie są dokładnie takie same) – haylem

Powiązane problemy