Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.io.*;
- import java.util.ArrayList;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.nio.ByteBuffer;
- import java.nio.channels.FileChannel;
- import java.util.Random;
- import java.util.zip.DataFormatException;
- import java.util.zip.Deflater;
- import java.util.zip.Inflater;
- public class Test {
- private static final int bucketSize = 1<<17;//in real world should not be const, but we bored horribly
- static final int zipLevel = 2;//feel free to experiement, higher compression (5+)is likely to be total waste
- static void writes(long[] a, File file, boolean sync) throws IOException{
- byte[] bucket = new byte[Math.min(bucketSize, Math.max(1<<13, Integer.highestOneBit(a.length >>3)))];//128KB bucket
- byte[] zipOut = new byte[bucket.length];
- final FileOutputStream fout = new FileOutputStream(file);
- FileChannel channel = fout.getChannel();
- try{
- ByteBuffer buf = ByteBuffer.wrap(bucket);
- //unfortunately java.util.zip doesn't support Direct Buffer - that would be the perfect fit
- ByteBuffer out = ByteBuffer.wrap(zipOut);
- out.putLong(a.length);//write length aka header
- if (a.length==0){
- doWrite(channel, out, 0);
- return;
- }
- Deflater deflater = new Deflater(zipLevel, false);
- try{
- for (int i=0;i<a.length;){
- i = puts(a, buf, i);
- buf.flip();
- deflater.setInput(bucket, buf.position(), buf.limit());
- if (i==a.length)
- deflater.finish();
- //hacking and using bucket here is tempting since it's copied twice but well
- for (int n; (n= deflater.deflate(zipOut, out.position(), out.remaining()))>0;){
- doWrite(channel, out, n);
- }
- buf.clear();
- }
- }finally{
- deflater.end();
- }
- }finally{
- if (sync)
- fout.getFD().sync();
- channel.close();
- }
- }
- static long[] reads(File file) throws IOException, DataFormatException{
- FileChannel channel = new FileInputStream(file).getChannel();
- try{
- byte[] in = new byte[(int)Math.min(bucketSize, channel.size())];
- ByteBuffer buf = ByteBuffer.wrap(in);
- System.out.println("Read channel size: " + in.length);
- channel.read(buf);
- buf.flip();
- long[] a = new long[(int)buf.getLong()];
- System.out.println("Read length: " + a.length);
- if (a.length==0)
- return a;
- int i=0;
- byte[] inflated = new byte[Math.min(1<<17, a.length*8)];
- ByteBuffer longBuffer = ByteBuffer.wrap(inflated);
- Inflater inflater = new Inflater(false);
- try{
- do{
- if (!buf.hasRemaining()){
- buf.clear();
- channel.read(buf);
- buf.flip();
- }
- inflater.setInput(in, buf.position(), buf.remaining());
- buf.position(buf.position()+buf.remaining());//simulate all read
- for (;;){
- int n = inflater.inflate(inflated,longBuffer.position(), longBuffer.remaining());
- if (n==0)
- break;
- longBuffer.position(longBuffer.position()+n).flip();
- for (;longBuffer.remaining()>7 && i<a.length;i++){//need at least 4 bytes to form an int
- a[i] = longBuffer.getLong();
- }
- longBuffer.compact();
- }
- }while (channel.position()<channel.size() && i<a.length);
- }finally{
- inflater.end();
- }
- // System.out.printf("read ints: %d - channel.position:%d %n", i, channel.position());
- return a;
- }finally{
- channel.close();
- }
- }
- private static void doWrite(FileChannel channel, ByteBuffer out, int n) throws IOException {
- out.position(out.position()+n).flip();
- while (out.hasRemaining())
- channel.write(out);
- out.clear();
- }
- private static int puts(long[] a, ByteBuffer buf, int i) {
- for (;buf.hasRemaining() && i<a.length;){
- buf.putLong(a[i++]);
- }
- return i;
- }
- private static long[] generateRandom(int len){
- Random r = new Random(17);
- long[] n = new long [len];
- for (int i=0;i<len;i++){
- n[i]= r.nextBoolean()?0: r.nextInt(1<<23);//limit bounds to have any sensible compression
- }
- return n;
- }
- public static void main(String[] args) throws Throwable{
- File file = new File("xxx.xxx");
- long[] n = generateRandom(3000000); //{0,2,4,1,2,3};
- long start = System.nanoTime();
- writes(n, file, false);
- long elapsed = System.nanoTime() - start;//elapsed will be fairer if the sync is true
- System.out.printf("File length: %d, for %d ints, ratio %.2f in %.2fms %n", file.length(), n.length, ((double)file.length())/8/n.length, java.math.BigDecimal.valueOf(elapsed, 6) );
- long[] m = reads(file);
- //compare, Arrays.equals doesn't return position, so it sucks/kinda
- for (int i=0; i<n.length; i++){
- if (m[i]!=n[i]){
- System.err.printf("Failed at %d%n",i);
- break;
- }
- }
- System.out.printf("All done!");
- };
- }
Advertisement
Add Comment
Please, Sign In to add comment