GZIP Java vs .NET
-
02-10-2019 - |
Domanda
utilizzando il seguente codice Java per comprimere / decomprimere byte [] per / da GZIP. In primo luogo il testo byte per byte gzip:
public static byte[] fromByteToGByte(byte[] bytes) {
ByteArrayOutputStream baos = null;
try {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
baos = new ByteArrayOutputStream();
GZIPOutputStream gzos = new GZIPOutputStream(baos);
byte[] buffer = new byte[1024];
int len;
while((len = bais.read(buffer)) >= 0) {
gzos.write(buffer, 0, len);
}
gzos.close();
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
return(baos.toByteArray());
}
Poi il metodo che va gli altri byte modo compressi per byte non compressi:
public static byte[] fromGByteToByte(byte[] gbytes) {
ByteArrayOutputStream baos = null;
ByteArrayInputStream bais = new ByteArrayInputStream(gbytes);
try {
baos = new ByteArrayOutputStream();
GZIPInputStream gzis = new GZIPInputStream(bais);
byte[] bytes = new byte[1024];
int len;
while((len = gzis.read(bytes)) > 0) {
baos.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
return(baos.toByteArray());
}
che ci sia alcun effetto dal momento che non sto scrivendo in un file gzip?
Inoltre ho notato che nella funzione standard C # che BitConverter legge i primi quattro byte e quindi la funzione MemoryStream Write viene chiamata con un punto iniziale di 4 e una lunghezza di ingresso lunghezza del buffer - 4. Così è che l'effetto sulla validità della testata?
Jim
Soluzione
Ho provato fuori, e non posso riprodurre il problema 'non valido GZip Header'. Ecco quello che ho fatto:
Java lato
Ho preso il vostro metodo di compressione Java insieme a questo java frammento:
public static String ToHexString(byte[] bytes){
StringBuilder hexString = new StringBuilder();
for (int i = 0; i < bytes.length; i++)
hexString.append((i == 0 ? "" : "-") +
Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
return hexString.toString();
}
Affinché questa applicazione Java minimalista, prendendo i byte di una stringa di prova, comprimendolo, e convertirlo in una stringa esadecimale dei dati compressi ...:
public static void main(String[] args){
System.out.println(ToHexString(fromByteToGByte("asdf".getBytes())));
}
... emette il seguente (ho aggiunto le annotazioni) :
1f-8b-08-00-00-00-00-00-00-00-4b-2c-4e-49-03-00-bd-f3-29-51-04-00-00-00
^------- GZip Header -------^ ^----------- Compressed data -----------^
C # lato
Ho scritto due metodi per la compressione e decompressione di un array di byte a un altro array di byte (metodo di compressione è solo per completezza, e le mie collaudi) :
public static byte[] Compress(byte[] uncompressed)
{
using (MemoryStream ms = new MemoryStream())
using (GZipStream gzs = new GZipStream(ms, CompressionMode.Compress))
{
gzs.Write(uncompressed, 0, uncompressed.Length);
gzs.Close();
return ms.ToArray();
}
}
public static byte[] Decompress(byte[] compressed)
{
byte[] buffer = new byte[4096];
using (MemoryStream ms = new MemoryStream(compressed))
using (GZipStream gzs = new GZipStream(ms, CompressionMode.Decompress))
using (MemoryStream uncompressed = new MemoryStream())
{
for (int r = -1; r != 0; r = gzs.Read(buffer, 0, buffer.Length))
if (r > 0) uncompressed.Write(buffer, 0, r);
return uncompressed.ToArray();
}
}
Insieme con una piccola funzione che prende una stringa esadecimale e giri di nuovo ad un array di byte ... (anche solo a scopo di test) :
public static byte[] ToByteArray(string hexString)
{
hexString = hexString.Replace("-", "");
int NumberChars = hexString.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
return bytes;
}
... ho fatto la seguente:
// Just hardcoded the output of the java program, convert it back to byte[]
byte[] fromjava = ToByteArray("1f-8b-08-00-00-00-00-00-00-00-" +
"4b-2c-4e-49-03-00-bd-f3-29-51-04-00-00-00");
// Decompress it with my function above
byte[] uncompr = Decompress(fromjava);
// Get the string out of the byte[] and print it
Console.WriteLine(System.Text.ASCIIEncoding.ASCII
.GetString(uncompr, 0, uncompr.Length));
Et voilà, l'output è:
asdf
Opere perfetto per me. Forse si dovrebbe verificare il metodo di decompressione nell'applicazione c #.
È detto nella tua domanda precedente si archiviano quei array di byte in un database, giusto? Forse si vuole verificare se i byte tornano dal database il modo in cui li metti in.
Altri suggerimenti
postando questo come una risposta in modo che il codice è decente.
Nota un paio di cose:
In primo luogo, il viaggio di andata al database non sembra avere alcun effetto. Java su entrambi i lati prodotto esattamente quello che ho messo in. Java in C # tutto bene ha lavorato con l'API ionica, come fatto in C # e Java fuori. Il che mi porta al secondo punto.
In secondo luogo, la mia decompressione originale era dell'ordine di:
public static string Decompress(byte[] gzBuffer)
{
using (MemoryStream ms = new MemoryStream())
{
int msgLength = BitConverter.ToInt32(gzBuffer, 0);
ms.Write(gzBuffer, 4, gzBuffer.Length – 4);
byte[] buffer = new byte[msgLength];
ms.Position = 0;
using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
{
zip.Read(buffer, 0, buffer.Length);
}
return Encoding.UTF8.GetString(buffer);
}
}
che dipendeva dal numero di byte interna, la tua legge l'intero file indipendentemente dal valore interno. Non so che cosa l'algoritmo ionico è. Distinti funziona allo stesso modo i metodi Java che ho usato. Questa è l'unica differenza che vedo. Grazie molto per fare tutto quel lavoro. Ricorderò quel modo di farlo. Grazie, Jim