I am currently working on a Project which is in Objective C.
I need to use Functions of Java class DataOutputStream like writeChars, writeLong, flush and some functions of ByteArrayOutputStream Class.
Specifically, what can I use in Objective C which has the same functionality as the DataOutputStream and ByteArrayOutputStream class?
This is the code i need to convert into Objective C.
public static byte[] getByteArray(String key, long counter) throws IOException
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
if (key != null)
{
dos.writeChars(key);
}
dos.writeLong(counter);
dos.flush();
byte[] data = bos.toByteArray();
return data;
}
NSLog();
the above method takes string and objects as arguments.
As,
NSLog(#"Hi this is demo of string printing.");
NSLog(#"Hi this is integer %d",intValue);//this is like printf isnt it?
EDIT:
Either %b, or convert it into NSData object and then print using %#. Obj-c uses %# for all kind of object.
unsigned int a = 0x000000FF;
NSLog(#"%x", a);//prints the most significant digits first
What you want is convert primitive data types into raw bytes.
NSMutableData* dataBuffer = [NSMutableData data]; //obj-c byte array
long long number = 123456LL; //note that long long is needed in obj-c to represent 64bit numbers
NSData* numberData = [NSData dataWithBytes:&number length:sizeof(number)];
[dataBuffer appendData:numberData];
NSString* text = #"abcdefg";
const char* rawText = [text cStringUsingEncoding:NSUTF8StringEncoding]; //java uses utf8 encoding
NSData* textData = [NSData dataWithBytes:rawText length:strlen(rawText)];
[dataBuffer appendData:textData];
return dataBuffer;
No flush() is necessary (I believe in Java is not neccessary with ByteArrayOutputStream either)
This is a bit simplified, note that when Java writes a string, the first two bytes are always the string length. Java also writes numbers in Big Endian. We are writing them in system byte-order. That shouldn't be a problem if you don't want to send the binary data to other devices.
You can switch byte order using utilities in CFByteOrderUtils.h or you can get the number in Big Endian directly by the following:
- (NSData*)bytesFromLongLong:(long long)number {
char buffer[8];
for (int i = sizeof(buffer) - 1; i >= 0; i--) {
buffer[i] = (number & 0xFF);
number >> 8;
}
return [NSData dataWithBytes:buffer length:sizeof(buffer)]
}
Related
In C#, I use the SerialPort Read function as so:
byte[] buffer = new byte[100000];
int bytesRead = serial.Read(buffer, 0, 100000);
In Processing, I use readBytes as so:
byte[] buffer = new byte[100000];
int bytesRead = serial.readBytes(buffer);
In Processing, I'm getting the incorrect byte values when I loop over the buffer array from the readBytes function, but when I just use the regular read function I get the proper values, but I can't grab the data into a byte array. What am I doing wrong in the Processing version of the code that's leading me to get the wrong values in the buffer array?
I print out the data the same way in both versions:
for(int i=0; i<bytesRead; i++){
println(buffer[i]);
}
C# Correct Output:
Processing Incorrect Output:
Java bytes are signed, so any value over 128 will overflow.
A quick solution is to do
int anUnsignedByte = (int) aSignedByte & 0xff;
to each of your bytes.
I have a code in Java which works fine, and I need to inflate the same data in python
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
public static byte[] Inflate(byte[] compressedContent) throws IOException {
ByteArrayOutputStream s = new ByteArrayOutputStream();
InflaterInputStream iis = new InflaterInputStream(new ByteArrayInputStream(compressedContent), new Inflater(true));
byte[] buffer = new byte[4096];
int len;
while ((len = iis.read(buffer)) != -1) {
s.write(buffer, 0, len);
}
iis.close();
s.flush();
s.close();
return s.toByteArray();
}
Using
StringUtils.newStringUtf8(inflate(Base64.decodeBase64("PZLHrptQAET_xevHE8VgnB1gyqVjig0bRLkUg-k9yr_HiZTsZo5mZjU_T1GSwHEMp7aCzenH6fR1-ivDae_gx7MwGuDwoWX6PwN3uYjFpDRK2XZRfnJQQXA5MIK3N_s7oEDFb9qruFmVNtmCtuuOX6qcTEVP5k-Hv7t-mVnfo-XgDa4LBkIt9lMmtKBz4kful_eDNBUONYQ95CXHBRY3dSlEYcC063oXC8hMkKLXRof6Re3vS8U1w-A0oRQt0spqnGifob-1orDhK-bMYflYVOR8KQC_YxVjjekaHuUxvQOZXBgdI4ubvl6z-p0BF-AjY2qNca48qY6j80Wa6Wxjvl8c31AG5V6vto8FG3vZ2c1jvt28MuvIdyjTx1otQPLMC71iOHjqtpFihNLmQVhPdSzbuM8rJ_eocJ4z12DzvFDZGwyeC109TGV2xjsQ32kv5VGB2NH1XFiGVd8xkE9PRI1oDHFwRck_25y3KlxMWKmlDrw7Br75nrunSsrNJbZwzq5rTRivAuhmBZz12RRacuxyeSz5ZIcMqFk8Il8U7nYEsLHHqLRP92oEGfvQZgfqLuuNWf-qlXqc56TiLpdjlfvAU-LwGG599wrdKST41sHeiKCbCZckNLW-aT8V0_tC7FzPh1pZWO6uykgGHtpOp0J9KzxKlPdXvwy9FTV0geUAmjERfR_mgwDciiqlr0qahOlKSMrW524DzAY4Fv8-18x1_XWCW1d-aFh-CE2dUfTXbw")))
The Java code works well, but I cannot convert it to Python as follows..
def Base64UrlDecode(data):
"""Decode base64, padding being optional.
:param data: Base64 data as an ASCII byte string
:returns: The decoded byte string.
"""
if isinstance(data, unicode):
data = data.encode('utf-8')
missing_padding = len(data) % 4
if missing_padding != 0:
data += b'=' * (4 - missing_padding)
return base64.decodestring(data)
url_decode = Base64UrlDecode(token) # The token is the same string as the above one.
# https://docs.python.org/2/library/zlib.html#zlib.compressobj
for i in range(-15, 32): # try all possible ones, but none works.
try:
decode = zlib.decompress(url_decode, i)
except:
pass
The true in Inflater(true)in Java means inflation of raw deflate data with no header or trailer. To get that same operation in Python, the second argument to zlib.decompress() must be -15. So you don't need to try different values there.
The next thing to check is your Base64 decoding. The result of that must be different in the two cases, so look to see where they are different to find your bug.
I need to save a binary stream, that I will later convert to text. Since binary streams don't exist in Java, I just saved my 'bits' in a stream of 'bytes' just to test my code. Now I have a stream of bytes where 1 bit is encoded on 1 byte.
byte [] stream = new byte [1500];
int str = 0;
byte [] data = new byte [1];
for (int i = 0; i<original.cols(); i++)
{
for (int j= 0; j<original.rows(); j++)
{
original.get(j,i, data);
if ((data[0]==0))
{
stream [str]=0;
str = str+1;
}
else
{
stream [str]=1;
str = str+1;
}
}
}
Can anyone help me to properly save my bits encoded in a stream of bytes, where 1 byte would represent 8 bits ?
A java.util.BitSet contains helper methods for dealing with raw bits, and conversions to and from byte arrays. In the following example, bytes will contain a single byte:
int numberOfBits = 8;
BitSet bitSet = new BitSet(numberOfBits);
bitSet.set(3, true);
bitSet.set(7, true);
byte[] bytes = bitSet.toByteArray();
I am trying to write a bunch of integers and a string into the byte buffer. Later this byte array will be written to the hard drive. Everything seems to be fine except when I am writing the string in the loop only the last character is written. The parsing of the string appears correct as I have checked that.
It appears to be the way I use the bbuf.put statement. Do I need to flush it after, and why does the .putInt statement work fine and not .put
//write the PCB from memory to file system
private static void _tfs_write_pcb()
{
int c;
byte[] bytes = new byte[11];
//to get the bytes from volume name
try {
bytes = constants.filename.getBytes("UTF-8"); //convert to bytes format to pass to function
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
ByteBuffer bbuf = ByteBuffer.allocate(bl_size);
bbuf = bbuf.putInt(rt_dir_start);
bbuf = bbuf.putInt(first_free_data_bl);
bbuf = bbuf.putInt(num_bl_fat);
bbuf = bbuf.putInt(bl_size);
bbuf = bbuf.putInt(max_rt_entries);
bbuf = bbuf.putInt(ft_copies);
for (c=0; c < vl_name.length(); c++) {
System.out.println((char)bytes[c]);
bbuf = bbuf.put(bytes[c]);
}
_tfs_write_block(1, bbuf.array());
}
ByteBuffer has a method for put'ting an array of byte. Is there a reason to put them one at a time? I note that put(byte) is abstract as well.
So the for loop is simplified to:
bbuf = bbuf.put(bytes, 6, bytes.length);
http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte:A-
EDIT: The Javadoc specifies that put(byte[]) begins at index 0, so use the form put(byte[], index, length) instead.
public final ByteBuffer put(byte[] src)
Relative bulk put method (optional operation).
This method transfers the entire content of the given source byte array
into this buffer. An invocation of this method of the form dst.put(a)
behaves in exactly the same way as the invocation
dst.put(a, 0, a.length)
Of course, it really should not matter HOW you insert the String bytes. I am just suggesting discovery experimentation.
This is my encryption program. Primarily used to encrypt Files(text)
This part of the program converts List<Integer> elements intobyte [] and writes it into a text file. Unfortunately i cannot provide the algorithm.
void printit(List<Integer> prnt, File outputFile) throws IOException
{
StringBuilder building = new StringBuilder(prnt.size());
for (Integer element : prnt)
{
int elmnt = element;
//building.append(getascii(elmnt));
building.append((char)elmnt);
}
String encryptdtxt=building.toString();
//System.out.println(encryptdtxt);
byte [] outputBytes = offo.getBytes();
FileOutputStream outputStream =new FileOutputStream(outputFile);
outputStream.write(outputBytes);
outputStream.close();
}
This is the decryption program where the decryption program get input from a .enc file
void getfyle(File inputFile) throws IOException
{
FileInputStream inputStream = new FileInputStream(inputFile);
byte[] inputBytes = new byte[(int)inputFile.length()];
inputStream.read(inputBytes);
inputStream.close();
String fylenters = new String(inputBytes);
for (char a:fylenters.toCharArray())
{
usertext.add((int)a);
}
for (Integer bk : usertext)
{
System.out.println(bk);
}
}
Since the methods used here, in my algorithm require List<Integer> byte[] gets converted to String first and then to List<Integer>and vice versa.
The elements while writing into a file during encryption do not match the elements read from the .enc file.
Is my method of converting List<Integer> to byte[] correct??
or is something else wrong? . I do know that java can't print extended ASCII characters so i used this .But, even this failed.It gives a lot of ?s
Is there a solution??
please help me .. and also how to do it for other formats(.png.mp3....etc)
The format of the encrypted file can be anything (it needn't be .enc)
thanxx
There are thousands of different 'extended ASCII' codes and Java supports about a hundred of them,
but you have to tell it which 'Charset' to use or the default often causes data corruption.
While representing arbitrary "binary" bytes in hex or base64 is common and often necessary,
IF the bytes will be stored and/or transmitted in ways that preserve all 256 values, often called "8-bit clean",
and File{Input,Output}Stream does, you can use "ISO-8859-1" which maps Java char codes 0-255 to and from bytes 0-255 without loss, because Unicode is based partly on 8859-1.
on input, read (into) a byte[] and then new String (bytes, charset) where charset is either the name "ISO-8859-1"
or the java.nio.charset.Charset object for that name, available as java.nio.charset.StandardCharSets.ISO_8859_1;
or create an InputStreamReader on a stream reading the bytes from a buffer or directly from the file, using that charset name or object, and read chars and/or a String from the Reader
on output, use String.getBytes(charset) where charset is that charset name or object and write the byte[];
or create an OutputStreamWriter on a stream writing the bytes to a buffer or the file, using that charset name or object, and write chars and/or String to the Writer
But you don't actually need char and String and Charset at all. You actually want to write a series of Integers as bytes, and read a series of bytes as Integers. So just do that:
void printit(List<Integer> prnt, File outputFile) throws IOException
{
byte[] outputBytes = new byte[prnt.size()]; int i = 0;
for (Integer element : prnt) outputBytes[i++] = (byte)element;
FileOutputStream outputStream =new FileOutputStream(outputFile);
outputStream.write(b);
outputStream.close();
// or replace the previous three lines by one
java.nio.file.Files.write (outputFile.toPath(), outputBytes);
}
void getfyle(File inputFile) throws IOException
{
FileInputStream inputStream = new FileInputStream(inputFile);
byte[] inputBytes = new byte[(int)inputFile.length()];
inputStream.read(inputBytes);
inputStream.close();
// or replace those four lines with
byte[] inputBytes = java.nio.file.Files.readAllBytes (inputFile.toPath());
for (byte b: inputBytes) System.out.println (b&0xFF);
// or if you really wanted a list not just a printout
ArrayList<Integer> list = new ArrayList<Integer>(inputBytes.length);
for (byte b: inputBytes) list.add (b&0xFF);
// return list or store it or whatever
}
Arbitrary data bytes are not all convertible to any character encoding and encryption creates data bytes including all values 0 - 255.
If you must convert the encrypted data to a string format the standard methods are to convert to Base64 or hexadecimal.
In encryption part:
`for (Integer element : prnt)
{
int elmnt = element;
//building.append(getascii(elmnt));
char b = Integer.toString(elmnt).charAt(0);
building.append(b);
}`
-->this will convert int to char like 1 to '1' and 5 to '5'