GZIPInputStream显示错误数据

时间:2014-06-23 14:11:14

标签: java libgdx

问题很简单,无论何时我添加GZipInputStream和GZipOutputStream,我的数据都会损坏。没有它们,一切正常。

我有以下代码:

public boolean loadAll() {
    FileHandle file = Gdx.files.external("TinyVoxel/world_comp.lvl");
    if (!file.exists())
        return false;

    InputStream in = file.read();

    try {
        in = new GZIPInputStream(in);

        int count = in.read();
        ErrorHandler.log("Count loading grids: " + count);

        int it = 0;
        while(in.available() > 0) {
            int x = in.read();
            int y = in.read();
            int z = in.read();

            Grid grid = createGrid(x, y, z);
            grid.loadGrid(in);

            it++;

            if (it % 10 == 0) {
                System.out.println("Loading: " + ((float)it * 100f / (float)count));
            }
        }
        in.close();
    } catch (IOException ex) {
        ErrorHandler.log("Failure saving!");
    }

    return true;
}

如果我删除了GZIPInputStream并且没有用GZIPOutputStream压缩原始数据(见下文,我删除了GZIPOutputStream),那么一切都很好。

public void saveAll() {
    Iterator<ObjectMap.Entry<List<Integer>, Grid>> it = terrainMap.entries().iterator();
    int count = 0;
    OutputStream out = Gdx.files.external("TinyVoxel/world_comp.lvl").write(false);

    try {
        out = new GZIPOutputStream(out);

        out.write(terrainMap.size);
        ErrorHandler.log("Count writing grids: " + terrainMap.size);

        while (it.hasNext()) {
            ObjectMap.Entry<List<Integer>, Grid> entry = it.next();
            List<Integer> pos = entry.key;
            final Grid grid = entry.value;
            grid.saveGrid(out);

            if (count % 10 == 0)
                System.out.println("Saving: " + ((float)count * 100f / (float) terrainMap.size));

            count++;
        }

        out.close();
    } catch (IOException ex) {
        ErrorHandler.log("Failure saving!");
    }

    ErrorHandler.log("Complete saving!");
}

值得注意的是,我在grid.loadGrid和grid.saveGrid中进行字节保存和加载。它可能是由这些操作引起的,但为什么它与常规Out和Inputstream一起工作正常?

修改

此外还有grid.loadGrid和grid.saveGrid函数的代码 - 至少重要的部分。

public boolean loadGrid(InputStream in) throws IOException {
    int count = in.read();

    palettesTotal = 0;
    for (int gx = 0; gx < Config.GRID_SIZE_X; gx++)
        for (int gy = 0; gy < Config.GRID_SIZE_Y; gy++)
            for (int gz = 0; gz < Config.GRID_SIZE_Z; gz++) {
                grids[gx][gy][gz] = (byte)0xff;
            }

    for (int i = 0; i < count; i++) {

        int gx = in.read();
        int gy = in.read();
        int gz = in.read();

        grids[gx][gy][gz] = (byte) (palettesTotal & 0xff);

        palettesTotal++;

        byte[] buff = new byte[Config.TINY_GRID_SIZE * 2];
        TinyGridContainer tinyGrid = bytePool.obtain();
        for (int ty = 0; ty < Config.TINY_GRID_SIZE; ty++)
            for (int tz = 0; tz < Config.TINY_GRID_SIZE; tz++) {
                in.read(buff, 0, buff.length);
                for (int tx = 0; tx < Config.TINY_GRID_SIZE; tx++) {
                    tinyGrid.grid[tx][ty][tz] = (short) ((buff[tx * 2] >> 2) & 0xff + buff[tx * 2 + 1] & 0xff);
                }
            }

        tinyGrids.put(Position.create(gx, gy, gz), tinyGrid);
    }
    ....
}

public void saveGrid(OutputStream out) throws IOException {
    out.write(x);
    out.write(y);
    out.write(z);

    out.write(palettesTotal);

    for (int gx = 0; gx < Config.GRID_SIZE_X; gx++)
       for (int gy = 0; gy < Config.GRID_SIZE_Y; gy++)
           for (int gz = 0; gz < Config.GRID_SIZE_Z; gz++) {
               if (grids[gx][gy][gz] != (byte) 0xff) {
                   // add tiny grid to pixmap
                   List<Integer> pos = Position.create(gx, gy, gz);
                   TinyGridContainer tinyGrid = tinyGrids.get(pos);

                   out.write(gx);
                   out.write(gy);
                   out.write(gz);

                   Position.free(pos);

                   byte[] buff = new byte[Config.TINY_GRID_SIZE * 2];
                   for (int ty = 0; ty < Config.TINY_GRID_SIZE; ty++)
                       for (int tz = 0; tz < Config.TINY_GRID_SIZE; tz++) {
                           for (int tx = 0; tx < Config.TINY_GRID_SIZE; tx++) {
                               buff[tx*2] = (byte)((tinyGrid.grid[tx][ty][tz] >> 2) & 0xff);
                               buff[tx*2+1] = (byte)(tinyGrid.grid[tx][ty][tz] & 0xff);
                           }
                           out.write(buff, 0, buff.length);
                       }
               }
           }
   }

1 个答案:

答案 0 :(得分:1)

史密斯先生的评论让我朝着正确的方向前进。

        byte[] buff = new byte[Config.TINY_GRID_SIZE * 2];
        TinyGridContainer tinyGrid = bytePool.obtain();
        for (int ty = 0; ty < Config.TINY_GRID_SIZE; ty++)
            for (int tz = 0; tz < Config.TINY_GRID_SIZE; tz++) {
                int cnt = 0;
                for (int tx = 0; tx < Config.TINY_GRID_SIZE; tx++) {
                    int id = tx * 2;

                    if (cnt <= id) {
                        cnt += in.read(buff, cnt, buff.length - cnt);
                    }

                    tinyGrid.grid[tx][ty][tz] = (short) ((buff[id] >> 2) & 0xff);

                    id++;
                    if (cnt <= id) {
                        cnt += in.read(buff, cnt, buff.length - cnt);
                    }

                    tinyGrid.grid[tx][ty][tz] += (short) (buff[id] & 0xff);
                }
            }