2012-12-27 13 views
8

alt kümelerindeki verilerin güçlü bir şekilde atlanması İkili bir akışı işliyorum ve ilgilenmeyeceğim bir veri aralığını verimli bir şekilde atlatarak işlenecek bazı verilere geçmem gerekiyor. Bir java.io.InputStream ve alt türlerinde

InputStream.skip(long)

teminat yolunda çok yapmaz: Verilerin

atlar üzerinde ve ıskarta n byte Bu giriş akımından. Atlama metodu, çeşitli nedenlerden ötürü, muhtemelen daha az sayıda baytın üzerinde atlama yapabilmektedir. Bu muhtemelen bir takım koşullardan kaynaklanabilir; n bayttan önce dosyanın sonuna ulaşılması sadece bir olasılıktır. Atlanan gerçek bayt sayısı döndürülür.

iki nedenden oturum ettiğini bilmek gerekir:

  1. akışı
  2. bayt Yeterince basit

atlandı erdi. Bununla birlikte, bu açıklamada ortaya çıkan cansızlık, örneğin, BufferedInputStream'un sadece bir kaç baytı atlayıp geri dönebileceği anlamına gelir. Tabii ki, bana sadece birkaçını atladığını söylüyor, ama nedenini açık değil.

Bu yüzden sorum şu: InputStream.skip(long)'u, akış sona erdiğinde veya atlama başarılı bir şekilde tamamlandığında ne şekilde kullanabileceğinizi bilerek kullanabilir misiniz?

cevap

8

Bence gerçekten sağlam uygulanmasını alabilirsiniz sanmıyorum. Bir şey için, EOF'deki davranış iyi tanımlanmamıştır. 8 bayt atlamak ve is.skip(8) 0 değerini döndürmek istiyorsam, tekrar denemem gerektiğine karar vermek önemsizdir, bazı uygulama EOF'de 0 değerini döndürmeyi seçerse, sonsuz bir döngü tehlikesi vardır. available() da güvenilir olmamalıdır.

/** 
* Skips n bytes. 
*/ 
public static void myskip(InputStream is, long n) throws IOException { 
    while(n > 0) { 
     long n1 = is.skip(n); 
     if(n1 > 0) { 
      n -= n1; 
     } else if(n1 == 0) { // should we retry? lets read one byte 
      if(is.read() == -1) // EOF 
       break; 
      else 
       n--; 
     } else // negative? this should never happen but... 
     throw new IOException("skip() returned a negative value - this should never happen"); 
    } 
} 

biz "gerçekten atlanır" bayt sayısını bilgilendirmek için bir değer döndürmek gerekmiyor:

Dolayısıyla, şu öneriyoruz? Ya da EOF'a ulaşıldığını bildiren bir boolean mı? Bunu sağlam bir şekilde yapamayız. Örneğin, FileInputStream nesnesi için skip(8) nesnesini, EOF'de olsak da, veya dosyada yalnızca 2 bayta sahip olsa bile it will return 8'u çağırırsak. Ancak yöntem, istediğimiz şeyi yapması bakımından sağlamdır: n bayt'ı atlayın (eğer mümkünse) ve işleme devam etmeme izin verin (eğer bir sonraki okunuşlarım geri dönerse -1 EOF'a ulaşıldığını bileceğim).

+0

Cevabınız, endişelendiğim şeyleri somut olarak detaylandırıyor. Uygulamada çalışmak için _seems_ kodunu gönderdim, ancak 'InputStream' uygulamasının tüm uygulamaları için çalışacağından emin değilim. Uzantınız ilginç görünüyor ve kısa bir süre içinde [ihtiyacım olan sınıfta] deneyeceğim (https://code.google.com/p/metadata-extractor/source/browse/Source/com/drew/lang/ StreamReader.java). Şu anda benim API'm sıranın başarılı olup olmadığını bildirmeye çalışıyor, bu yüzden garanti mümkün değilse istemci kodunu değiştirmem gerekebilir. Çok teşekkürler. –

+0

'FileInputStream.skip()' meselesini düzeltebilirsiniz: 'n-1' bayt için' while' döngüsünü kullanın; sonra, döngüden sonra, bir kez 'in.read()' yi çağır. '-1' değerini döndürürse, atlamanız EOF'ye çarptı, aksi takdirde atlama başarılı oldu. Ayrıca, üstte bir n == 0' kontrol etmeyi unutmayın. –

+0

@KannanGoundan İlginç bir öneri. Bir dezavantaj, elbette, bazı senaryolarda, performansı etkileyebilecek olan akıştan en az iki okuma (bir "atlama" artı bir "okuma") gerektirmesidir. – leonbloy

2

Bu n bayt atladığı için çalışıyor görünüyor: o Kitaplığıma geçirilebilecek InputStream tüm uygulamaları için çalışacağını net değil ancak

long skippedTotal = 0; 
while (skippedTotal != n) { 
    long skipped = _stream.skip(n - skippedTotal); 
    assert(skipped >= 0); 
    skippedTotal += skipped; 
    if (skipped == 0) 
     break; 
} 
boolean skippedEnough = skippedTotal == n; 

. Kendi tamponlu atlama yöntemimi uygulayıp uygulamayacağımı merak ediyorum. skip() yöntem sözleşme oldukça tuhaf olduğu için

+0

Herhangi bir "InputStream" uygulamasının sözleşmeden nasıl kaç bayt gerçekten atlandığını döndürdüğünü belirten nasıl çıkacağını göremiyorum. – EJP

+0

@EJP, Katılıyorum. Bir tür IO artefaktı (arabelleğe alma gibi) nedeniyle ya da akış sona erdiği için daha az bayt atlanıp atlanmadığını bilmek endişe duyuyorum. Akış bitmemişse, "atlama" yine de sıfır olabilir.Hangi noktada daha fazla bayt olmadığından atlama işleminin işe yaramadığını biliyorsunuzdur, belki de ağ üzerinden bayt beklemektedir. –

+2

Bu konuda gördüğüm sorun, "atlandı" = 0 olduğunda yeniden denemememiz gerektiğinden emin olamayız. Dahası, boole 'atpedEnough' güvenilmez. Cevabımı gör. – leonbloy

İlgili konular