Zip byte[] in Kotlin. Java code to Kotlin - java

I'm trying to use this Java code but converting it to Kotlin in Android Studio, but I don't find a equivalent in kotlin for setSize(..) and .length in Kotlin. Could anyone help me?
public static byte[] zipBytes(String filename, byte[] input) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
ZipEntry entry = new ZipEntry(filename);
entry.setSize(input.length);
zos.putNextEntry(entry);
zos.write(input);
zos.closeEntry();
zos.close();
return baos.toByteArray();
}

Array in Kotlin has size field instead of Java array length and size field is Int in Kotlin, but ZipEntry.setSize(long size) accepts only long. So you can do something like this:
entry.setSize(input.size.toLong())
Or in more Kotlin idiomatic way:
entry.size = input.size.toLong()

when you write a byteArray in kotlin like this :
val byteArray = ByteArray(1024)
var length = byteArray.size
documentation says
An array of bytes. When targeting the JVM, instances of this class are represented as byte[].
#constructor Creates a new array of the specified [size], with all elements initialized to zero.
to prove it, checking the byte code created is this:
byte[] byteArray = new byte[1024];
int test = byteArray.length;
therefor in your case a can code like this.
entry.size = byteArray.size
but type of size is int and entry.size needs a long value, just add .toLong() to size for fixing this issue.

Try to use this code:
Import:
import java.io.IOException
import java.text.DecimalFormat
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
And you code in kotlin:
#Throws(IOException::class)
fun zipBytes(filename: String?, input: ByteArray): ByteArray? {
val baos = ByteArrayOutputStream()
val zos = ZipOutputStream(baos)
val entry = ZipEntry(filename)
entry.size = input.size.toLong()
zos.putNextEntry(entry)
zos.write(input)
zos.closeEntry()
zos.close()
return baos.toByteArray()
}

Related

How to get the byte array data from Reference-arithmetic-coding result

I am trying to implement arithmetic coding using Java,and I found this project:Reference-arithmetic-coding. But its' input and output are both file, I wanna get the byte array that is the coding result from AdaptiveArithmeticCompress.compress(). Here is what I did:
I add a function in class AdaptiveArithmeticCompress named AACompress:
public static byte[] AACompress(short[] delta) throws IOException{
byte[] bytedelta = TypeConversion.ShortToByte_little(delta);
ByteArrayInputStream bis = new ByteArrayInputStream(bytedelta);
BitOutputStream out = new BitOutputStream(new ByteArrayOutputStream());
compress(bis,out);
return out.toBytearray();
}
and create out.toBytearray() to convert outputstream to byte array.
public byte[] toBytearray() {
ByteArrayOutputStream baos = (ByteArrayOutputStream) output;
return baos.toByteArray();
}
But when I compared result byte array with result file which is output of AdaptiveArithmeticCompress.compress(InputStream in, BitOutputStream out), I found that
short[] delta = ...;
byte[] coding = AdaptiveArithmeticCompress.AACompress(delta);
coding.length is 1 less than out.buf.length, the last byte of out.buf is missing, so the coding result is wrong.
I am new to Java, this problem has been confusing me several days. Can anyone help me? Thanks a lot.
I solved this problem by adding a close method in ArithmeticEncoder class
public void close() throws IOException {
output.close();
}
And the missing byte has been added into outputstream.

Reading large number of bytes from GZIPInputStream

I am reading a gzipped file through GZIPInputStream. I want to read a large amount of data at once, but no matter how many bytes I ask the GZIPInputStream to read, it always reads far less number of bytes. For example,
val bArray = new Array[Byte](81920)
val fis = new FileInputStream(new File(inputFileName))
val gis = new GZIPInputStream(fis)
val bytesRead = gis.read(bArray)
The bytes read are always somewhere around 1800 bytes, while it should be nearly equal to the size of bArray, which is 81920 in this case. Why is it like this? Is there a way to solve this problem, and really have more number of bytes read?
I would try using akka-streams in case you have large amount of data.
implicit val system = ActorSystem()
implicit val ec = system.dispatcher
implicit val materializer = ActorMaterializer()
val fis = new FileInputStream(new File(""))
val gis = new GZIPInputStream(fis)
val bfs: BufferedSource = Source.fromInputStream(gis)
bfs exposes the Flow api for stream processing.
You can also get a stream from that:
val ss: Stream[String] = bfs.bufferedReader().lines()
The read might always return fewer bytes than you ask for, so in general you always have to loop, reading as many as you want.
In other words, giving GZIPInputStream a big buffer doesn't mean it will be filled on a given request.
import java.util.zip.GZIPInputStream
import java.io.FileInputStream
import java.io.File
import java.io.InputStream
import java.io.FilterInputStream
object Unzipped extends App {
val inputFileName = "/tmp/sss.gz"
val bArray = new Array[Byte](80 * 1024)
val fis = new FileInputStream(new File(inputFileName))
val stingy = new StingyInputStream(fis)
val gis = new GZIPInputStream(stingy, 80 * 1024)
val bytesRead = gis.read(bArray, 0, bArray.length)
println(bytesRead)
}
class StingyInputStream(is: InputStream) extends FilterInputStream(is) {
override def read(b: Array[Byte], off: Int, len: Int) = {
val n = len.min(1024)
super.read(b, off, n)
}
}
So instead, loop to drain instead of issuing one read:
import reflect.io.Streamable.Bytes
val sb = new Bytes {
override val length = 80 * 1024L
override val inputStream = gis
}
val res = sb.toByteArray()
println(res.length) // your explicit length
I'm not saying that's the API to use, it's just to demo. I'm too lazy to write a loop.
OK, I found the solution. There is a version of constructor for GZIPInputStream that also takes the size of the buffer.

How to unzip file from InputStream

I'm trying to get a zip file from the server.
Im using HttpURLConnection to get InputStream and this is what i have:
myInputStream.toString().getBytes().toString() is equal to [B#4.....
byte[] bytes = Base64.decode(myInputStream.toString(), Base64.DEFAULT);
String string = new String(bytes, "UTF-8");
string == �&ܢ��z�m����y....
I realy tried to unzip this file but nothing works, also there is so many questions, should I use GZIPInputStream or ZipInputStream? Do I have to save this stream as file, or I can work on InputStream
Please help, my boss is getting impatient:O
I have no idea what is in this file i have to find out:)
GZipInputStream and ZipInputStream are two different formats. https://en.wikipedia.org/wiki/Gzip
It is not a good idea to retrieve a string directly from the stream.From an InputStream, you can create a File and write data into it using a FileOutputStream.
Decoding in Base 64 is something else. If your stream has already decoded the format upstream, it's OK; otherwise you have to encapsulate your stream with another input stream that decodes the Base64 format.
The best practice is to use a buffer to avoid memory overflow.
Here is some Kotlin code that decompresses the InputStream zipped into a file. (simpler than java because the management of byte [] is tedious) :
val fileBinaryDecompress = File(..path..)
val outputStream = FileOutputStream(fileBinaryDecompress)
readFromStream(ZipInputStream(myInputStream), BUFFER_SIZE_BYTES,
object : ReadBytes {
override fun read(buffer: ByteArray) {
outputStream.write(buffer)
}
})
outputStream.close()
interface ReadBytes {
/**
* Called after each buffer fill
* #param buffer filled
*/
#Throws(IOException::class)
fun read(buffer: ByteArray)
}
#Throws(IOException::class)
fun readFromStream(inputStream: InputStream, bufferSize: Int, readBytes: ReadBytes) {
val buffer = ByteArray(bufferSize)
var read = 0
while (read != -1) {
read = inputStream.read(buffer, 0, buffer.size)
if (read != -1) {
val optimizedBuffer: ByteArray = if (buffer.size == read) {
buffer
} else {
buffer.copyOf(read)
}
readBytes.read(optimizedBuffer)
}
}
}
If you want to get the file from the server without decompressing it, remove the ZipInputStream() decorator.
Usually, there is no significant difference between GZIPInputStream or ZipInputStream, so if at all, both should work.
Next, you need to identify whether the zipped stream was Base64 encoded, or the some Base64 encoded contents was put into a zipped stream - from what you put to your question, it seems to be the latter option.
So you should try
ZipInputStream zis = new ZipInputStream( myInputStream );
ZipEntry ze = zis.getNextEntry();
InputStream is = zis.getInputStream( ze );
and proceed from there ...
basically by setting inputStream to be GZIPInputStream should be able to read the actual content.
Also for simplicity using IOUtils package from apache.commons makes your life easy
this works for me:
InputStream is ; //initialize you IS
is = new GZIPInputStream(is);
byte[] bytes = IOUtils.toByteArray(is);
String s = new String(bytes);
System.out.println(s);

Convert ZIP to byte array without saving the output to file

I have a ZIP file and when I convert it into byte array and encode it, I am unable to print the encoded format without writing it into file.
Could anyone help in solving this issue?
My code is
InputStream is = null;
OutputStream os = null;
is = new FileInputStream("C:/Users/DarkHorse/Desktop/WebServicesTesting/PolicyCredit.zip");
os = new FileOutputStream("D:/EclipseTestingFolder/EncodedFile1.txt");
int bytesRead = 0;
int chunkSize = 10000000;
byte[] chunk = new byte[chunkSize];
while ((bytesRead = is.read(chunk)) > 0)
{
byte[] ba = new byte[bytesRead];
for(int i=0;i<ba.length;i++)
{
ba[i] = chunk[i];
}
byte[] encStr = Base64.encodeBase64(ba);
os.write(encStr);
}
os.close();
is.close();
}
My Output in the file is
UEsDBBQAAAAIANGL/UboGxdAAQUAAK0WAAAQAAAAUG9saWN5Q3JlZGl0LnhtbJVY3Y6rNhC+r9R34AlqSPankSwkdtNskbLZKOk5Va8QC95d6wRIDZyeffszxgSMGUPKFcx8M/b8egwN87IWcZ6waF+cePLp//qLAw/d8BOL/mRxykRL6sk89T1KLq8adx1XLHp5i55YzkRc8SL3F6534y69O0oQpia6K6LiLTqwpBBpKdUPCRq
But when I am trying to print it on the screen, I am getting in this way
8569115686666816565656573657871764785981117112010065658185656575488765656581656565658571571159787785381517410890711084876110104116987486895189541147810467431145782515265108113838097110107831191071001167811510798769075791075386975681675753100541198273689012110110210211512212010383777185807570991205677479856101103119785655738799905411997704399101807611247471137665119471005666797647109821201211078276
You need to create a string representation of Base 64 encoded data.
System.out.println( new String(encStr, Charset.forName("UTF-8")));
Here are some other examples Base 64 Print Question
String Class
Assuming your result array byte[] encStr = Base64.encodeBase64(ba) is actually the encoded string, try the following:
System.out.println(new String(bytes, Charset.defaultCharset());
If you are using JDK 7 you can use Files.readAllBytes(path)
Your code would be much simpler like below:
Path path = Paths.get("C:/Users/DarkHorse/Desktop/WebServicesTesting/PolicyCredit.zip");
byte[] data = Files.readAllBytes(path);
byte[] encStr = Base64.encodeBase64(data);
System.out.println( new String(encStr));
Your will be able to print on console.

Assigning to a byte array in Java

I have a byte array I want to assign as follows:
First byte specifies the length of the string: (byte)string.length()
2nd - Last bytes contain string data from string.getBytes()
Other than using a for loop, is there a quick way to initialize a byte array using bytes from two different variables?
You can use System.arrayCopy() to copy your bytes:
String x = "xx";
byte[] out = new byte[x.getBytes().length()+1];
out[0] = (byte) (0xFF & x.getBytes().length());
System.arraycopy(x.getBytes(), 0, out, 1, x.length());
Though using something like a ByteArrayOutputStream or a ByteBuffer like other people suggested is probably a cleaner approach and will be better for your in the long run :-)
How about ByteBuffer ?
Example :
ByteBuffer bb = ByteBuffer.allocate(string.getBytes().length +1 );
bb.put((byte) string.length());
bb.put(string.getBytes());
While ByteBuffer is generally the best way to build up byte arrays, given the OP's goals I think the following will be more robust:
public static void main(String[] argv)
throws Exception
{
String s = "any string up to 64k long";
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(bos);
out.writeUTF(s);
out.close();
byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
DataInputStream in = new DataInputStream(bis);
String s2 = in.readUTF();
}
How about ByteArrayOutputStream?

Categories

Resources