After running a Junit test for String serialization, it is failed and gave me the following results:
Expected: "netmodel"
Actual: "l"
The serialize method as follows
public static void serializeString(String objectToSerialize, OutputStream outputStream) {
byte[] bytesArr = objectToSerialize.getBytes();
serializeInt(bytesArr.length, outputStream);
try {
outputStream.write(bytesArr);
} catch (IOException e) {
e.printStackTrace();
}
}
And my deserialize method as follows
public static String deserializeString(InputStream inputStream) {
String deserializeObject = "";
char asciiToChar;
int stringByteArrayLength = deserializeInt(inputStream);
byte[] databytesArr = new byte[stringByteArrayLength];
try {
inputStream.read(databytesArr, 0, stringByteArrayLength);
}
catch (IOException e) {
e.printStackTrace();
}
for (int i = 0; i < databytesArr.length; i++) {
asciiToChar = (char) databytesArr[i];
deserializeObject = "" + Character.toString(asciiToChar);
}
return deserializeObject;
}
Finally, I wrote a unit test as follows
public class StringSerializerTest {
private InputStream iStream;
private ByteArrayOutputStream oStream;
#Before
public void init() {
oStream = new ByteArrayOutputStream();
}
String serialzeAndDeserializeObject(String stringValue) {
OutputStreamUtil.serializeString(stringValue, oStream);
iStream = new ByteArrayInputStream(oStream.toByteArray());
return InputStreamUtil.deserializeString(iStream);
}
#Test
public void equals_equal() {
String stringValue = "netmodel";
String deserializedStringValue = serialzeAndDeserializeObject(stringValue);
assertThat(deserializedStringValue).isEqualTo(stringValue);
}
}
what was wrong? and how to fix it?
You are reassigning the entire value of deserializeObject during each iteration of
for (int i = 0; i < databytesArr.length; i++) {
asciiToChar = (char) databytesArr[i];
deserializeObject = "" + Character.toString(asciiToChar);
}
This results in only the last character (l in this case) being stored in deserializeObject. This loop should append the next character to the deserializeObject as in the following:
for (int i = 0; i < databytesArr.length; i++) {
asciiToChar = (char) databytesArr[i];
deserializeObject += Character.toString(asciiToChar);
}
The corrected deserialization logic would be:
public static String deserializeString(InputStream inputStream) {
String deserializeObject = "";
char asciiToChar;
int stringByteArrayLength = deserializeInt(inputStream);
byte[] databytesArr = new byte[stringByteArrayLength];
try {
inputStream.read(databytesArr, 0, stringByteArrayLength);
}
catch (IOException e) {
e.printStackTrace();
}
for (int i = 0; i < databytesArr.length; i++) {
asciiToChar = (char) databytesArr[i];
deserializeObject += Character.toString(asciiToChar);
}
return deserializeObject;
}
The error was already reported by Justin Albano.
However take also care of strings with non-ASCII: like special characters.
Something like the following. Also one should close at the end to ensure flushing in case of a buffered stream. And theoretically a read could yield only a non-blocking part of the array. DataOutputStream has nice methods, though you seem to roll your own serialisation.
public static void serializeString(String objectToSerialize, OutputStream outputStream)
throws IOException {
byte[] bytesArr = objectToSerialize.getBytes(StandardCharsets.UTF_8);
serializeInt(bytesArr.length, outputStream);
outputStream.write(bytesArr);
}
public static String deserializeString(InputStream inputStream)
throws IOException {
int stringByteArrayLength = deserializeInt(inputStream);
byte[] databytesArr = new byte[stringByteArrayLength];
readFully(inputStream, databytesArr);
return new String(databytesArr, StandardCharsets.UTF_8);
}
private static void readFully(InputStream inputStream, byte[] bytes) throws IOException {
int i = 0;
while (i < bytes.length) {
int nread = inputStream.read(bytes, i, bytes.length - i);
if (nread <= 0) {
throw new IOException("Premature EOF");
}
i += nread;
}
}
Mind that StandardCharsets is not in Android SDK, only standard Java.
Related
Can any one help me write decrypt method for my XOR encryptor. So how i'm encrypt:
I'm making XOR
public static String idEncrypt(String id, String key)throws Exception
{
if (id == null)
return null;
if (key.length() == 0)
return id;
String utfID="", utfKey="";
try
{
utfID = new String(id.getBytes(), "UTF-8");
utfKey = new String(key.getBytes(), "UTF-8");
}
catch (UnsupportedEncodingException e)
{
Log.e("utf8", "conversion", e);
}
StringBuilder sb = new StringBuilder();
for(int i = 0; i < utfID.length(); i++)
sb.append((char)(utfID.charAt(i) ^ utfKey.charAt(i % utfKey.length())));
String result = sb.toString();
return toHex(result.getBytes());
}
Converting bytes to hex:
public static String toHex(byte[] buf) {
if (buf == null)
return "";
StringBuffer result = new StringBuffer(2*buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
private final static String HEX = "0123456789abcdef";
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
}
Actually all of my trying to decrypt result of this crypts failed =(
May be some on explains me how work with it?
P.S: the results of my trying is strings like "X¨»¾RkÖ_êQ", but must be 16 symbols of numbers and letters.
UPD:
My fromHEX() method
public static String fromHex(String hex) {
return new String(toByte(hex));
}
public static byte[] toByte(String hexString) {
int len = hexString.length()/2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
return result;
}
I have a byte array which is filled by a serial port event and code is shown below:
private InputStream input = null;
......
......
public void SerialEvent(SerialEvent se){
if(se.getEventType == SerialPortEvent.DATA_AVAILABLE){
int length = input.available();
if(length > 0){
byte[] array = new byte[length];
int numBytes = input.read(array);
String text = new String(array);
}
}
}
The variable text contains the below characters,
"\033[K", "\033[m", "\033[H2J", "\033[6;1H" ,"\033[?12l", "\033[?25h", "\033[5i", "\033[4i", "\033i" and similar types..
As of now, I use String.replace to remove all these characters from the string.
I have tried new String(array , 'CharSet'); //Tried with all CharSet options but I couldn't able to remove those.
Is there any way where I can remove those characters without using replace method?
I gave a unsatisfying answer, thanks to #OlegEstekhin for pointing that out.
As noone else answered yet, and a solution is not a two-liner, here it goes.
Make a wrapping InputStream that throws away escape sequences. I have used a PushbackInputStream, where a partial sequence skipped, may still be pushed back for reading first. Here a FilterInputStream would suffice.
public class EscapeRemovingInputStream extends PushbackInputStream {
public static void main(String[] args) {
String s = "\u001B[kHello \u001B[H12JWorld!";
byte[] buf = s.getBytes(StandardCharsets.ISO_8859_1);
ByteArrayInputStream bais = new ByteArrayInputStream(buf);
EscapeRemovingInputStream bin = new EscapeRemovingInputStream(bais);
try (InputStreamReader in = new InputStreamReader(bin,
StandardCharsets.ISO_8859_1)) {
int c;
while ((c = in.read()) != -1) {
System.out.print((char) c);
}
System.out.println();
} catch (IOException ex) {
Logger.getLogger(EscapeRemovingInputStream.class.getName()).log(
Level.SEVERE, null, ex);
}
}
private static final Pattern ESCAPE_PATTERN = Pattern.compile(
"\u001B\\[(k|m|H\\d+J|\\d+:\\d+H|\\?\\d+\\w|\\d*i)");
private static final int MAX_ESCAPE_LENGTH = 20;
private final byte[] escapeSequence = new byte[MAX_ESCAPE_LENGTH];
private int escapeLength = 0;
private boolean eof = false;
public EscapeRemovingInputStream(InputStream in) {
this(in, MAX_ESCAPE_LENGTH);
}
#Override
public int read(byte[] b, int off, int len) throws IOException {
for (int i = 0; i < len; ++i) {
int c = read();
if (c == -1) {
return i == 0 ? -1 : i;
}
b[off + i] = (byte) c;
}
return len;
}
#Override
public int read() throws IOException {
int c = eof ? -1 : super.read();
if (c == -1) { // Throw away a trailing half escape sequence.
eof = true;
return c;
}
if (escapeLength == 0 && c != 0x1B) {
return c;
} else {
escapeSequence[escapeLength] = (byte) c;
++escapeLength;
String esc = new String(escapeSequence, 0, escapeLength,
StandardCharsets.ISO_8859_1);
if (ESCAPE_PATTERN.matcher(esc).matches()) {
escapeLength = 0;
} else if (escapeLength == MAX_ESCAPE_LENGTH) {
escapeLength = 0;
unread(escapeSequence);
return super.read(); // No longer registering the escape
}
return read();
}
}
}
User calls EscapeRemovingInputStream.read
this read may call some read's itself to fill an byte buffer escapeSequence
(a push-back may be done calling unread)
the original read returns.
The recognition of an escape sequence seems grammatical: command letter, numerical argument(s). Hence I use a regular expression.
So I use the following methods
(File is converted to Byte Array through 'convertFileToByteArray()', then written to .txt file by 'convertByteArrayToBitTextFile()'
to convert any kind of file into a Binary Text file (and by that I mean only 1's and 0's in human readable form.)
public static byte[] convertFileToByteArray(String path) throws IOException
{
File file = new File(path);
byte[] fileData;
fileData = new byte[(int)file.length()];
FileInputStream in = new FileInputStream(file);
in.read(fileData);
in.close();
return fileData;
}
public static boolean convertByteArrayToBitTextFile(String path, byte[] bytes)
{
String content = convertByteArrayToBitString(bytes);
try
{
PrintWriter out = new PrintWriter(path);
out.println(content);
out.close();
return true;
}
catch (FileNotFoundException e)
{
return false;
}
}
public static String convertByteArrayToBitString(byte[] bytes)
{
String content = "";
for (int i = 0; i < bytes.length; i++)
{
content += String.format("%8s", Integer.toBinaryString(bytes[i] & 0xFF)).replace(' ', '0');
}
return content;
}
Edit: Additional Code:
public static byte[] convertFileToByteArray(String path) throws IOException
{
File file = new File(path);
byte[] fileData;
fileData = new byte[(int)file.length()];
FileInputStream in = new FileInputStream(file);
in.read(fileData);
in.close();
return fileData;
}
public static boolean convertByteArrayToBitTextFile(String path, byte[] bytes)
{
try
{
PrintWriter out = new PrintWriter(path);
for (int i = 0; i < bytes.length; i++)
{
out.print(String.format("%8s", Integer.toBinaryString(bytes[i] & 0xFF)).replace(' ', '0'));
}
out.close();
return true;
}
catch (FileNotFoundException e)
{
return false;
}
}
public static boolean convertByteArrayToByteTextFile(String path, byte[] bytes)
{
try
{
PrintWriter out = new PrintWriter(path);
for(int i = 0; i < bytes.length; i++)
{
out.print(bytes[i]);
}
out.close();
return true;
}
catch (FileNotFoundException e)
{
return false;
}
}
public static boolean convertByteArrayToRegularFile(String path, byte[] bytes)
{
try
{
PrintWriter out = new PrintWriter(path);
for(int i = 0; i < bytes.length; i++)
{
out.write(bytes[i]);
}
out.close();
return true;
}
catch (FileNotFoundException e)
{
return false;
}
}
public static boolean convertBitFileToByteTextFile(String path)
{
try
{
byte[] b = convertFileToByteArray(path);
convertByteArrayToByteTextFile(path, b);
return true;
}
catch (IOException e)
{
return false;
}
}
I do this to try methods of compression on a very fundamental level, so please let's not discuss why use human-readable form.
Now this works quite well so far, however I got two problems.
1)
It takes foreeeever (>20 Minutes for 230KB into binary text). Is this just a by-product of the relatively complicated conversion or are there other methods to do this faster?
2) and main problem:
I have no idea how to convert the files back to what they used to be. Renaming from .txt to .exe does not work (not too surprising as the resulting file is two times larger than the original)
Is this still possible or did I lose Information about what the file is supposed to represent by converting it to a human-readable text file?
If so, do you know any alternative that prevents this?
Any help is appreciated.
The thing that'll cost you most time is the construction of an ever increasing String. A better approach would be to write the data as soon as you have it.
The other problem is very easy. You know that every sequence of eight characters ('0' or '1') was made from a byte. Hence, you know the values of each character in an 8-character block:
01001010
^----- 0*1
^------ 1*2
^------- 0*4
^-------- 1*8
^--------- 0*16
^---------- 0*32
^----------- 1*64
^------------ 0*128
-----
64+8+2 = 74
You only need to add the values where an '1' is present.
You can do it in Java like this, without even knowing the individual bit values:
String sbyte = "01001010";
int bytevalue = 0;
for (i=0; i<8; i++) {
bytevalue *= 2; // shifts the bit pattern to the left 1 position
if (sbyte.charAt(i) == '1') bytevalue += 1;
}
Use StringBuilder to avoid generating enormous numbers of unused String instances.
Better yet, write directly to the PrintWriter instead of building it in-memory at all.
Loop through every 8-character subsequence and call Byte.parseByte(text, 2) to parse it back to a byte.
I was searching a code in java for sending multiple files over a socket, I found this code which consists of a TX main, a RX main and a class for all the dirty work I assume. Code runs with no errors but I have a questions for the experts,
where exactly in the code, the user types the files that he/she want to send to the server ?
And in the server main, what is the location where the server stores the received file, and with what name ?
Where exactly in this code ( TX / RX / ByteStream), should I amend to specify what file goes in ?
I would like to input the filename myself in the client (TX) side, where futher on I would include a JFileChooser for the user to select Graphically which file to send.
package file_rx;
import java.io.*;
import java.net.*;
public class File_RX implements Runnable
{
private static final int port = 4711;
private Socket socket;
public static void main(String[] _)
{
try
{
ServerSocket listener = new ServerSocket(port);
while (true)
{
File_RX file_rec = new File_RX();
file_rec.socket = listener.accept();
new Thread(file_rec).start();
}
}
catch (java.lang.Exception e)
{
e.printStackTrace(System.out);
}
}
public void run()
{
try
{
InputStream in = socket.getInputStream();
int nof_files = ByteStream.toInt(in);
for (int cur_file = 0; cur_file < nof_files; cur_file++)
{
String file_name = ByteStream.toString(in);
File file = new File(file_name);
ByteStream.toFile(in, file);
}
}
catch (java.lang.Exception e)
{
e.printStackTrace(System.out);
}
}
}
package file_tx;
import java.io.*;
import java.net.*;
public class File_TX
{
private static final int port = 4711;
private static final String host = "localhost";
public static void main(String[] args)
{
try
{
Socket socket = new Socket(host, port);
OutputStream os = socket.getOutputStream();
int cnt_files = args.length;
ByteStream.toStream(os, cnt_files);
for (int cur_file = 0; cur_file < cnt_files; cur_file++)
{
ByteStream.toStream(os, args[cur_file]);
ByteStream.toStream(os, new File(args[cur_file]));
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
package file_rx;
import java.io.*;
public class ByteStream
{
private static byte[] toByteArray(int in_int)
{
byte a[] = new byte[4];
for (int i = 0; i < 4; i++)
{
int b_int = (in_int >> (i*8)) & 255;
byte b = (byte) (b_int);
a[i] = b;
}
return a;
}
private static int toInt(byte[] byte_array_4)
{
int ret = 0;
for (int i = 0; i < 4; i++)
{
int b = (int) byte_array_4[i];
if (i < 3 && b < 0)
{
b = 256 + b;
}
ret += b << (i * 8);
}
return ret;
}
public static int toInt(InputStream in) throws java.io.IOException
{
byte[] byte_array_4 = new byte[4];
byte_array_4[0] = (byte)in.read();
byte_array_4[1] = (byte)in.read();
byte_array_4[2] = (byte)in.read();
byte_array_4[3] = (byte)in.read();
return toInt(byte_array_4);
}
public static String toString(InputStream ins) throws java.io.IOException
{
int len = toInt(ins);
return toString(ins, len);
}
private static String toString(InputStream ins, int len) throws java.io.IOException
{
String ret = new String();
for (int i = 0; i < len; i++)
{
ret += (char) ins.read();
}
return ret;
}
public static void toStream(OutputStream os, int i) throws java.io.IOException
{
byte [] byte_array_4 = toByteArray(i);
os.write(byte_array_4);
}
public static void toStream(OutputStream os, String s) throws java.io.IOException
{
int len_s = s.length();
toStream(os, len_s);
for (int i = 0; i < len_s; i++)
{
os.write((byte) s.charAt(i));
}
os.flush();
}
private static byte[] toByteArray(InputStream ins, int an_int) throws java.io.IOException
{
byte[] ret = new byte[an_int];
int offset = 0;
int numRead = 0;
int outstanding = an_int;
while ((offset < an_int) && (numRead = ins.read(ret, offset, outstanding)) > 0)
{
offset += numRead;
outstanding = an_int - offset;
}
if (offset < ret.length)
{
//throw new Exception("Could not completely read from stream, numRead =" + numRead + ", ret.lenght = " + ret.length);
}
return ret;
}
private static void toFile(InputStream ins, FileOutputStream fos, int len, int buf_size) throws java.io.IOException, java.io.FileNotFoundException
{
byte[] buffer = new byte[buf_size];
int len_read = 0;
int total_len_read = 0;
while (total_len_read + buf_size <= len)
{
len_read = ins.read(buffer);
total_len_read += len_read;
fos.write(buffer, 0, len_read);
}
if (total_len_read < len)
{
toFile(ins, fos, len - total_len_read, buf_size / 2);
}
}
private static void toFile(InputStream ins, File file, int len) throws java.io.IOException, java.io.FileNotFoundException
{
FileOutputStream fos = new FileOutputStream(file);
toFile(ins, fos, len, 1024);
}
public static void toFile (InputStream ins, File file) throws java.io.IOException, java.io.FileNotFoundException
{
int len = toInt(ins);
toFile(ins, file, len);
}
public static void toStream(OutputStream os, File file) throws java.io.IOException, java.io.FileNotFoundException
{
toStream(os, (int) file.length());
byte b[] = new byte[1024];
InputStream is = new FileInputStream(file);
int numRead = 0;
while ((numRead = is.read(b)) > 0)
{
os.write(b, 0, numRead);
}
os.flush();
}
}
The names (and paths) of the files to be transmitted are specified as arguments to the main method in the File_TX class. On the server side (File_RX class), the files will be saved relatively to the current directory of the File_RX.class file, having the same relative path as the input arguments above.
i convert a mp3 file into byte array and i read from byte array but it shows null pointer exception on line number 15
my code:
public class MainClass {
static byte[] bytesarray = null;
public static void main(String args[]) {
try {
FileInputStream fis = new FileInputStream("D:\\taxi.mp3");
try {
fis.read(bytesarray, 0, 32);
System.out.println(bytesarray.length);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
ByteArrayInputStream in = new ByteArrayInputStream(bytesarray);
for (int i = 0; i < 32; i++) {
int c;
while ((c = in.read()) != -1) {
if (i == 0) {
System.out.print((char) c);
} else {
System.out.print(Character.toUpperCase((char) c));
}
}
System.out.println();
}
}
}
static byte[] bytesarray = new byte[32]; should do the work, you didn't initialize your array...
See the documentation of read.
static byte[] bytesarray = new byte[32];