Different results ByteArrayOutputStream Java and C# - java

UPD:
For answers about encoding:
Am use UTF-8 everywhere
I'am try use ByteArrayOutputStream on C#.
I have a string of data:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567896ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567896
For java i use the method:
String a = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567896ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567896";
byte[] bArr = a.getBytes();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(bArr.length);
DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(byteArrayOutputStream);
deflaterOutputStream.write(bArr);
deflaterOutputStream.close();
bArr = byteArrayOutputStream.toByteArray();
System.out.println("out: "+Base64.getEncoder().encodeToString(bArr));
So, for as a result i get the string:
eJxzdHJ2cXVz9/D08vbx9fMPCAwKDgkNC4+IjEpMSk5JTUvPyMzKzsnNyy8oLCouKS0rr6isMjA0MjYxNTO3sDRzpEw7AHuTKoM=
For C# am use next code:
string source = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567896ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567896";
byte[] bArr_source = Encoding.UTF8.GetBytes(source);
MemoryStream byteArrayOutputStream = new MemoryStream(bArr_source.Length);
DeflaterOutputStream dos = new DeflaterOutputStream(byteArrayOutputStream);
dos.Write(bArr_source, 0, bArr_source.Length);
dos.Finish();
dos.Close();
bArr_source = byteArrayOutputStream.ToArray();
Console.WriteLine(Convert.ToBase64String(bArr_source));
But in C# iam get a different line:
eJyly8MBgAAAAMCVMp7Zdr9su+kbovsfRTMsxwuiJCuqphumZTuu5wdhFCdplhdlVTdt1w/jNC/rth/ndT8vAEIwgmI4QWI/+wd7kyqD
Why is this happening and how can I fix the problem?

There is no problem.
Both results are valid zlib streams with a check value that checks out, and both decompress to the exact same thing.
There is no assurance that two different compressors will produce the same output with the same input. The only assurance is that when you decompress, you get the same thing you started with. And you are.
I do find it a little odd that the C# code is producing a dynamic block when the result can be four bytes shorter with a fixed block. I suspect that you are using a much older version of .NET that used a compressor that was poorly written (internally at Microsoft). It now uses zlib, and wouldn't make that mistake. Yet I emphasize, the result is still entirely valid and usable.

Related

Equivalent Java function Base64.encode(byte, 0) in Swift

I have the following function in Java(write inside an Android app)
Bitmap bm = BitmapFactory.decodeFile(stringPath);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos); // bm is the bitmap object era quality 100
byte[] byteData = baos.toByteArray();
byte[] newB = Base64.encode(byteData,0);
It get an Image file and convert it to a byte array.
I need that to work on Swift.
I was able to convert the byteData to Int8, the equivalent of byte array in Swift.
I use the code below:
let filename = "RES4010110001"
let test_image:UIImage = UIImage(named: filename)!
let dataImage = UIImageJPEGRepresentation(test_image, 1)! as Data
var bytes: [Int8] = dataImage.map{Int8(bitPattern: $0)}
When I print this data using print(bytes) I got the same results on iOS and Android when I compare the "byteData" from Android and "bytes" from iOS
But I don't know what is the Java equivalent function below on Swift
Base64.encode(byteData,0);
How can I create an equivalent function on Swift of the function above?
For me, it appears that this function is encoding a byte array. But I have no idea of how I can encode a Int8 Array.
I said Int8 because for me, Int8 is the Swift equivalent of byte type in Java.
edit: I want to encode a Int8 array, I guess this is what the Java function (the function in the post title) is doing inside the Android app.
You can use base64EncodedData to encode your Data to get an encoded Data, rather than working with [Int8].
The Java code passes 0 (DEFAULT) as the flags. According to the docs, this means it's compliant with RFC 2045. RFC 2045 says that lines should be no more than 76 characters, so we should pass lineLength76Characters. RFC 2045 also requires CRLF as line endings, but base64EncodedData seems to insert them automatically even if we don't pass endLineWithCarriageReturn and endLineWithLineFeed.
let filename = "RES4010110001"
if let testImage = UIImage(named: filename),
let dataImage = testImage.jpegData(compressionQuality: 1) {
let encodedData = dataImage.base64EncodedData(options: [.lineLength76Characters])
} else {
// failed to get the UIImage, or the JPEG data, handle the error here...
}
I suggest that you do not work with [Int8] here. The byte[]s in the Java code are clearly not just "lists of numbers between -128 and 127". They represent data buffers, and those are represented by the Data struct in Swift. Don't worry, Both Data and [Int8] share a very similar set of protocol conformances, like MutableCollection, RangeReplaceableCollection, RandomAccessCollection etc. You can do almost everything you can do to an Int8 array, to a Data.
I was able to find an definite answer using part of the answer created by
#Sweeper and from another answer published here on Stackoverflow
let filename = "RES4010110001"
let test_image:UIImage = UIImage(named: filename)!
let dataImage = UIImageJPEGRepresentation(test_image, 1)! as Data // use apenas este que é correto, o galvez usa jpg no android
let dataImageStringBase64:String = dataImage.base64EncodedString(options: [.lineLength76Characters])
let byteArray = [UInt8](dataImageStringBase64.utf8)
The answer posted by #Sweeper just miss this line
let byteArray = [UInt8](dataImageStringBase64.utf8)
This last line of code made the code works perfectly for me.

Is there a way to encrypt/decrypt using Bouncy Castle without using compression

I'm looking for a way to encrypt/decrypt files/byte arrays without calling compression of input. To be more precises don't want to use something like
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(algorithm);
PGPUtil.writeFileToLiteralData(comData.open(bOut), PGPLiteralData.BINARY, new File(fileName));
Any reference, code sample is more than welecome,
Thanks.
You avoid adding compression in PGP by simply not adding the code that does it. For your question to be sensible, I would expect you to post an example that has signing/encryption + compression, then we could suggest how to remove the compression bits.
Actually the simplest way for you might be to just set "uncompressed" like this:
new PGPCompressedDataGenerator(algorithm, CompressionAlgorithmTags.UNCOMPRESSED)
The simpler way to do that is to chose CompressionAlgorithmTags.UNCOMPRESSED. If you do that, when you decrypt the file, from the object JcaPGPObjectFactory you still receive a PGPCompressedData (to be decompressed) instead of a PGPLiteralData.
To receive directly a PGPLiteralData, you could avoid at all the compression.
Taking your code as an example, you could write:
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
PGPUtil.writeFileToLiteralData(bOut, PGPLiteralData.BINARY, new File(fileName));

Java: How to restore string data which was compressed with python's zlib encoder

I send data through the socket from python to java.
So on the python 2.7 side I have:
s = "this is test str"
compressed = s.encode('zlib')
push_to_tcp_socket(compressed)
So I need to restore initial string on the java side. How I could do that?
You will need to send gthe length of the string, or close the connection so you know where the last byte is.
The most likely class to help you is the DeflatorInputStream which youc an use once the bytes have been read. This is a bare wrapper for the zlib class. I haven't tested it works with python but it's you best option.
You can try other compressions like Snappy or LZ4 which have cross platform support.
I assumed you already know the networking part on Java. You can use Inflater class to get your string like in javadocs
// Decompress the bytes
Inflater decompresser = new Inflater();
decompresser.setInput(output, 0, compressedDataLength);
byte[] result = new byte[100];
int resultLength = decompresser.inflate(result);
decompresser.end();
//Then create string in java i assumed you are using python 2 and string is ASCII
String str = new String(result,"US-ASCII")

Netica error or compression error? "buffer to decompress gzip 'internal' is too small"

I'm using the Netica Java library in my code to read in a bayes net, enter findings, and save the updated bayes net in a byte array. The byte array saves perfectly fine (as far as I can tell) but I can't seem to load it back in using the ByteArrayInputStream.
My code is:
Environ env = new EnvironI( null );
ByteArrayInputStream bais = new ByteArrayInputStream( myBinaryData );
bais.close();
Net model = new Net( new Streamer( bais, "templateFile.neta", env );
It fails on the last line with the following error:
stderr: norsys.netica.NeticaException:
************** E R R O R ***************
** ErrorNumber = 2734
** ErrorSeverity = ERROR_ERR
** ErrorCategory =
** ErrorMessage = In function Net(Streamer inStream) constructor: buffer to decompress gzip 'internal' is too small (is 3082 but -981804177 needed)
Note that there are specific applications of the Netica library here. I should also note that this works fine on my OSX machine but seems to break on a Linux box.
Any ideas?
I have determined the issue.
I mentioned that I read in a bayes net prior and that code looks like this:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Streamer stream = new Streamer( baos, "myNetaFile.neta", env );
net.write( stream );
byte[] bytesToEncode = baos.toByteArray();
stream.flush();
String encoded = Base64.encodeBase64String( bytesToEncode );
The above code is actually correct. The binary was getting corrupted somehow when I was reading it back in. My issue was I had the .toByteArray() and .flush() lines swapped.
If anybody else runs into this issue using Netica, keep in mind correct order of operations!

Write and read byte[] from file

I'm looking for something simple (no external lib preferably) to write and load a byte[] from a file. More or less something like [Python's pickle][1].
byte[] bytes = new byte[10];
ByteBuffer bbuf = new ByteBuffer.allocate(bytes.length);
bbuf.wrap(bytes); // edited due to Jon Skeet's answer
CharBuffer cbuf = bbuf.asCharBuffer();
cbuf.put("t");
FileOutputStream test = new FileOutputStream("somebytes");
test.write(bytes);
test.close();
The problem seems to be that I cannot read the Object structure from a file like that. In a hex-editor furthermore the file "somebytes" contains just a couple or 0s. So it doesn't seem the FileOutputStream puts any of the content ("t" or the byte-equivalent) into it.
[1] http://wiki.python.org/moin/UsingPickle
You've allocated a byte buffer with the size of bytes, but that doesn't mean the byte buffer is associated with the byte array. You can wrap a byte array using ByteBuffer.wrap.
Here's a minimal change to your code which does write the t into the file:
byte[] bytes = new byte[10];
ByteBuffer bbuf = ByteBuffer.wrap(bytes);
CharBuffer cbuf = bbuf.asCharBuffer();
cbuf.put("t");
FileOutputStream test = new FileOutputStream("somebytes");
test.write(bytes);
test.close();
Note that for real code you should use a try/finally block to make sure the file is always closed regardless of exceptions.
However, this is a long way from serialization. Java does have its own binary serialization - see ObjectOutputStream and ObjectInputStream. Personally I usually avoid this sort of serialization however, as it can be very brittle in the face of changes to classes. There are various other approaches to serialization, such as using Thrift or Protocol Buffers for binary serialization, or serializing to XML, JSON or some other human-readable format.
You can
seek(position)
b = read(length)
Then b will be an array of bytes of your length.
Sorry - on rereading you're looking for writing, not reading.
A simpler version of the same thing is.
byte[] bytes = new byte[10];
bytes[1] = 't';
FileOutputStream test = new FileOutputStream("somebytes");
test.write(bytes);
test.close();
There are plenty of examples on how to read/write byte[] from files on the web. try google.

Categories

Resources