A munkahelyemen sajnos én vagyok az, aki észreveszi azokat a hibákat, amelyek felett mások átsiklanak. Ez azért rossz, mert unalmas tesztelési munkákat is kell végeznem. Így történt, hogy egy bioinformatikai program tesztelése során furcsa anomáliára figyeltem fel. A program több szálon futott, számtalan ideiglenes állományt írt és olvasott. Ezalatt felzabált 100GB helyet, majd eredményül visszaadott 2GB-ot.
A hiba nem hagyott nyugodni, ezért megnéztem a forráskódot is. Mivel bioinformatikus vagyok, a programozók általában úgy tekintenek rám, mint valami Szkript Kölyökre, aki csak Perl-ben tud turkálni. Emberhiány esetén adnak programozós feladatot, de az is elég marginális, mintha félnének, hogy összedöntöm a verzió-követő rendszert. A nyár és a szabadságok ideje viszont megnyitotta az utat előttem, hogy megmutassam, mit tudok.
A hibát sikerült visszavezetnem egy fájl másoló metódusra, ahol NIO-t használtak. Emlékeztem is rá egy megbeszélésből, ahol a programozók bőszen magyarázták az előnyeit. A forráskódban viszont találtam egy tutorial kódot. A változók más néven szerepeltek, de egyébként kínos hasonlóságot mutatott ezze. Az egyetlen probléma, hogy a kód csak 2GB alatti fájloknál működik. Korrekt formája ez lenne:
import java.io.*;
Mert el kell olvasni a dokumentációt is, nem csak kimásolni a kódot.
import java.nio.channels.FileChannel;
public class niotest {
public static void main(String[] args){
File sfile = new File(args[0]);
File dfile = new File(args[1]);
try{
dfile.createNewFile();
}
catch(Exception e){
e.printStackTrace();
}
FileChannel from = null;
FileChannel to = null;
try{
from = new FileInputStream(sfile).getChannel();
to = new FileOutputStream(dfile).getChannel();
System.out.printf("File size: %d\n", from.size());
long written = 0;
while(written < from.size()){
written += to.transferFrom(from, written, from.size() - written);
}
System.out.printf("Written: %d\n", written);
from.close();
to.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}