This discussion is archived
5 Replies Latest reply: Aug 2, 2012 12:59 AM by gimbal2 RSS

ZIP file created in JAVA doesn't work as it is

952771 Newbie
Currently Being Moderated
I've recently decided to write a launcher for my project. It simply downloads updated files from my server, unpacks them, merges some of the files (because their content varies on settings of the launcher) and packs them into one .zip file.

I'm sure the downloading and merging processes work perfectly, but the last one - zipping - doesn't.

The .zip file is created correctly, but when I put it into the game dir, the game won't start (says it's corrupted). But if I open it with WinRar (yes, it opens without errors - the "Test" function shows no errors, too) and just add one, random file inside, the game STARTS!

Seems like WinRar re-creates the zip file in a correct way, but I can't make my launcher to do so.

Here's my code:
package launcher;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import javax.swing.JOptionPane;
import javax.swing.JLabel;


class Files implements Runnable
{     
     private final static String SEPARATOR = System.getProperty("file.separator");
     /** Local dir where the files will be downloaded */
     static String storage_dir = /*System.getProperty("user.dir") + */"temp";
     
     /** Local dir where the downloaded zips will be stored */
     static String download_dir = storage_dir + SEPARATOR + "pobierane";
     
     /** Local dir where the unpacked files will be stored */
     static String unpack_dir = storage_dir + SEPARATOR + "wypakowane";
     
     /** Local dir where the joined files will be stored */
     static String data_dir = storage_dir + SEPARATOR + "data";
     
     private String game_dir;
     private JLabel msg;
     

     
     
     
     Files (String gd, JLabel msg)
     {
          game_dir = gd;
          this.msg = msg;
     }
     
     
     public void run()
     {
          //System.out.println("START");
          System.out.println("Wypakowuję pliki");
          msg.setText("Wypakowuję pliki...");
          unzipFiles();
          System.out.println("Łączę pliki");
          msg.setText("Łączę pliki...");
          joinAllFiles();
          System.out.println("Tworzę plik PAK");
          msg.setText("Tworzę plik PAK...");
          createPAK();
          System.out.println("Kopiuję PAK do katalogu gry");
          msg.setText("Kopiuję PAK do katalogu gry...");
          copyPAK();
          
          //unzip("D:\\Gry\\Aion\\l10n\\1_enu\\data\\data.pak", "D:\\testowy");
          
          System.out.println("Usuwam tymczasowe pliki");
          msg.setText("Usuwam tymczasowe pliki...");
          try {
               delete(new File(unpack_dir));
               delete(new File(data_dir));
          } catch (IOException e) {
               e.printStackTrace();
          }
          createTempDirs();
          //System.out.println("STOP");
     }
     
     static public void createTempDirs()
     {
          String[] dirs_to_create = { download_dir, unpack_dir, data_dir };
          for (String dir : dirs_to_create)
          {
               File f = new File(dir);
               if (!f.exists()) f.mkdirs();
          }
     }
     public static void joinFiles(String[] files, String output, String main_tag, String encoding)
     {
          try
          {
               File o = new File(unpack_dir + SEPARATOR + output);
               if (o.exists()) o.delete();
               
               FileWriter output_file = new FileWriter(o);
               output_file.write("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\r\n<" + main_tag + ">");
               String a;
               for (String rfn : files)
               {
                    BufferedReader br = new BufferedReader(new FileReader(unpack_dir + SEPARATOR + rfn));
                    while ((a = br.readLine()) != null)
                    {
                         output_file.write("\r\n" + a);
                    }
                    br.close();
               }
               output_file.write("\r\n</" + main_tag + ">");
               output_file.close();
          } catch (IOException exc)
          {
               System.err.println(exc.toString());
          }
     }
     
     private void joinAllFiles()
     {
          String[][] filesToJoin = {
               {"strings" + SEPARATOR + "client_strings_order.xml", "strings" + SEPARATOR + "client_strings_questy.xml", "strings" + SEPARATOR + "client_strings_quest_items_name.xml", "strings" + SEPARATOR + "client_strings_quest_items_desc.xml", "strings" + SEPARATOR + "client_strings_title_name.xml", "strings" + SEPARATOR + "client_strings_title_desc.xml"},
               {"strings" + SEPARATOR + "client_strings_skill_name.xml", "strings" + SEPARATOR + "client_strings_skill_desc.xml"},
               {"strings" + SEPARATOR + "client_strings_item_name.xml", "strings" + SEPARATOR + "client_strings_item_desc.xml"},
               {"strings" + SEPARATOR + "client_strings_item2_name.xml", "strings" + SEPARATOR + "client_strings_item2_desc.xml"}
          };
          String[] destFiles = {
               "strings" + SEPARATOR + "client_strings_quest.xml",
               "strings" + SEPARATOR + "client_strings_skill.xml",
               "strings" + SEPARATOR + "client_strings_item.xml",
               "strings" + SEPARATOR + "client_strings_item2.xml"
          };
          
          String[] destEncodings = {
               "utf-16",     
               "utf-16",     
               "utf-16",     
               "utf-16"
          };
          String[] destTags = {
               "strings",
               "strings",
               "strings",
               "strings"
          };
          
          for (int i=0; i<filesToJoin.length; ++i)
          {
               joinFiles(filesToJoin, destFiles[i], destTags[i], destEncodings[i]);
               for (String f : filesToJoin[i])
               {
                    System.err.println("Usuwam plik: " + f);
                    if (!new File(unpack_dir + SEPARATOR + f).delete()) System.err.println("Nie można usunąć pliku: " + f);
               }
          }
     }
     
     private void createPAK()
     {
          
          try {
               zipDir(data_dir + SEPARATOR + "data.zip", unpack_dir);
          } catch (Exception e) {
               e.printStackTrace();
          }
     }
     
     static public int isFileUpdated (URL url, File local)
     {
          try {
               long local_length = 0;
               if (local.exists()) local_length = local.length();
               long url_length = url.openConnection().getContentLength();
               if (url_length == 162) url_length = 0;
               System.out.println("Sprawdzam: -- LOCAL: " + String.valueOf(local_length) + " --- URL: " + String.valueOf(url_length) + " -- LOCAL: " + local.getPath() + ", URL: " + url.getPath());
               if (local_length == url_length) return 1; else return 0;
          } catch (IOException e) {
               e.printStackTrace();
          }
          return -1;
     }
     
     private void copyPAK()
     {
          String destPath = game_dir + SEPARATOR + "l10n" + SEPARATOR + "1_enu" + SEPARATOR + "data";
          String data = getRealPath(destPath);
          if (data == "") {
               try {
                    java.nio.file.Files.createDirectories(new File(destPath).toPath());
                    data = destPath;
               } catch (IOException e) {
                    e.printStackTrace();
               }
               System.out.println("Tworzę potrzebne foldery w katalogu gry -- " + data);
          }
          if (new File(data).exists())
          {
               try {
                    if (!java.nio.file.Files.move(
                              new File(data_dir + SEPARATOR + "data.zip").toPath(),
                              new File(data + SEPARATOR + "data.pak").toPath(),
                              java.nio.file.StandardCopyOption.REPLACE_EXISTING).toFile().exists())
                         JOptionPane.showMessageDialog(null, "Nie można skopiować paczki do folderu: " + data);
               } catch (IOException e) {
                    e.printStackTrace();
               }
               
          }
     }
     
     private String getRealPath(String pathToCheck)
     {
          StringBuffer path = new StringBuffer();
          String[] pathSlices = pathToCheck.split("@" + SEPARATOR + "@");
          
          for (String dir : pathSlices)
          {
               File currentDir = new File(dir);
               // Folder istnieje, dodaj go do ścieżki
               if (currentDir.exists())
                    path.append(currentDir + SEPARATOR);
               // Folder nie istnieje, sprawdź, czy jest pod inną nazwą
               else
               {
                    if (path.length() == 0) return "";
                    String[] currentPathFiles = new File(path.toString()).list();
                    for (String c : currentPathFiles)
                    {
                         if (c.toLowerCase() == dir.toLowerCase())
                         {
                              path.append(c + SEPARATOR);
                              break;
                         }
                    }
               }
          }
          return path.toString();
     }
     
     static public ArrayList<String> getFilesToDownload(ArrayList<String> server_files)
     {
          ArrayList<String> filestodownload = new ArrayList<String>();
          
          String fn;
          for (String sv : server_files)
          {
               fn = sv.substring(sv.lastIndexOf('/') + 1);
               try {
                    int updated = isFileUpdated(new URL(sv), new File(download_dir + SEPARATOR + fn));
                    if (updated == 0)
                    {
                         System.out.println("Muszę pobrać: -- LOCAL: " + fn + " --- URL: " + sv);
                         filestodownload.add(sv);
                    }
                    else if (updated == -1)
                    {
                         JOptionPane.showMessageDialog(null, "Plik: " + fn + " nie może zostać pobrany. Zgłoś to do kogoś z IronSquadu!");
                         return new ArrayList<String>();
                    }
               } catch (MalformedURLException e) {
                    e.printStackTrace();
               }
          }
          
          return filestodownload;
     }
     
@SuppressWarnings("rawtypes")
     private static void unzip(String strZipFile, String strDest) {
try
{
File fSourceZip = new File(strZipFile);
String zipPath = strDest;
//System.out.println(zipPath + " created");

ZipFile zipFile = new ZipFile(fSourceZip);
Enumeration e = zipFile.entries();

while(e.hasMoreElements())
{
ZipEntry entry = (ZipEntry)e.nextElement();
File destinationFilePath = new File(zipPath,entry.getName());

//create directories if required.
destinationFilePath.getParentFile().mkdirs();

//if the entry is directory, leave it. Otherwise extract it.
if(entry.isDirectory())
{
     continue;
}
else
{
//System.out.println("Extracting " + destinationFilePath);

/*
* Get the InputStream for current entry
* of the zip file using
*
* InputStream getInputStream(Entry entry) method.
*/
BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));

int b;
byte buffer[] = new byte[1024];

/*
* read the current entry from the zip file, extract it
* and write the extracted file.
*/
FileOutputStream fos = new FileOutputStream(destinationFilePath);
BufferedOutputStream bos = new BufferedOutputStream(fos, 1024);

while ((b = bis.read(buffer, 0, 1024)) != -1)
{
     bos.write(buffer, 0, b);
}

//flush the output stream and close it.
bos.flush();
bos.close();

//close the input stream.
bis.close();
}
}
zipFile.close();
}
catch(IOException ioe)
{
System.out.println("IOError :" + ioe + " -- IN FILE: " + strZipFile);
}

}
     
     private void unzipFiles()
     {
          String[] files_to_unzip = new File(download_dir).list();
          for (String file : files_to_unzip)
          {
               unzip(download_dir + SEPARATOR + file, unpack_dir);
          }
     }
     
     public static void delete(File f) throws IOException {
          if (f.isDirectory()) {
          for (File c : f.listFiles())
          delete(c);
          }
          if (!f.delete())
          throw new FileNotFoundException("Failed to delete file: " + f);
     }

     private static void zipDir(String zipFileName, String dir) throws Exception {
          File dirObj = new File(dir);
          ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
          System.out.println("Creating : " + zipFileName);
          addDir(dirObj, out);
          out.close();
          }

          static void addDir(File dirObj, ZipOutputStream out) throws IOException {
          File[] files = dirObj.listFiles();
          byte[] tmpBuf = new byte[1024];

          for (int i = 0; i < files.length; i++) {
          if (files[i].isDirectory()) {
          addDir(files[i], out);
          continue;
          }
          String fap = files[i].getAbsolutePath();
          String rel_path = fap.substring(fap.indexOf("wypakowane") + 11).replace("\\", "/");
          FileInputStream in = new FileInputStream(fap);
          System.out.println(" Adding: " + rel_path);
          out.putNextEntry(new ZipEntry(rel_path));
          int len;
          while ((len = in.read(tmpBuf)) > 0) {
          out.write(tmpBuf, 0, len);
          }
          out.closeEntry();
          in.close();
          }
          }
}
("wypakowane" is the directory that contains all the files I want to put into ZIP file.)

I just compared both archives - the one created by my java app and the one created by WinRar by adding random file. They are identical, have the same CRCs, same attributes and unpack correctly. But the game crashes with the first one, and runs smoothly with the second one. I'm running out of ideas. Any help?

Edited by: 949768 on 2012-07-30 05:28