Android: Trying to test sockets - java

I'm trying to test socket communication in Android Java, but can't seem to get a mock working.
First of all, using Mockito, mock(Socket.class) throws an Exception java.lang.VerifyError.
So I coded my mock like so:
public void testMyTest(){
final ByteArrayOutputStream os = new ByteArrayOutputStream();
final ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
try{
byte[] buffer = new byte[6];
os.write("poulet".getBytes());
is.read(buffer, 0, 6);
Log.w(LOG_TAG, "Read result:" + (new String(buffer, "UTF-8")));
} catch(IOException e){}
}
However is is not reading from os when I call os.write(). The raw result is [B#42204320 and, in string form, it looks like ������������. I tried commenting os.write() but nothing changed.
Does anyone know how to link an input stream to read form an output stream?
To test my classes I just called
final Socket mockedSocket1 = new Socket();
final Socket mockedSocket2 = new Socket();
when(mockedSocket1.getInputStream()).thenReturn(is);
when(mockedSocket2.getOutputStream()).thenReturn(os)
So that my classes get the linked output and input streams that I'm going to test with.
Thanks a lot!

The is's buffer will always be empty.
This: ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray()); just creates an ByteArrayInputStream with an empty buffer, that buffer won't change when you write something to the ByteArrayOutputStream.
public byte[] toByteArray()
Creates a newly allocated byte array. Its size is the current size of this output stream and the valid contents of the buffer have been copied into it.
...
What you can do is to create the ByteArrayInputStream after you write something to the ByteArrayOutputStream, eg:
try (ByteArrayOutputStream os = new ByteArrayOutputStream();){
byte[] buffer = new byte[6];
os.write("poulet".getBytes("UTF-8"));
try(ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());){
is.read(buffer, 0, 6);
System.out.println("Read result:|" + (new String(buffer, "UTF-8") + "|"));
}
} catch (IOException e) {
}

Related

writing a string to a zip file using ZipOutputStream

Ultimately the goal is just to zip a string and have that as a string in java
public void zip() {
try {
String myTestString = "a zip file test and another test";
InputStream in = new ByteArrayInputStream(myTestString.getBytes());
OutputStream out = new ByteArrayOutputStream();
ZipOutputStream zipOut = new ZipOutputStream(out);
ZipEntry zipEntry = new ZipEntry("wtf.txt");
zipOut.putNextEntry(zipEntry);
zipOut.write(myTestString.getBytes(),0,myTestString.getBytes().length);
zipOut.close();
myTestString = out.toString();
out.close();
System.out.println(myTestString);
// just a test if I can read the file
in = new ByteArrayInputStream(myTestString.getBytes());
out = new FileOutputStream("c:\\t\\string.zip");
byte[] allBytes = new byte[(int) myTestString.getBytes().length];
in.read(allBytes);
out.write(allBytes);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
I have found I can write a string to a zipfile using
public void zipStringToFile2() {
try {
FileOutputStream fos = new FileOutputStream("c:/t/compressed.zip");
ZipOutputStream zipOut = new ZipOutputStream(fos);
String myTestString = "a zip file test and another test";
int buffer = myTestString.getBytes().length;
// byte[] myBytes = myTestString.getBytes();
ByteArrayOutputStream out = new ByteArrayOutputStream(buffer);
ZipEntry zipEntry = new ZipEntry("wtf.txt");
zipOut.putNextEntry(zipEntry);
zipOut.write(myTestString.getBytes(),0,buffer);
zipOut.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
but I cannot get the output of zipOut to write to a string and then have the string write to a file and then via the OS open the zipfile. How can that be done?
myTestString = out.toString();
This doesn't do what you want. bytes aren't strings. toString() doesn't give useful information (it is a debugging tool). Keep the byte array (.toByteArray()).
out.close();
close the stream after you retrieved the data? Don't do that. Close first. (not that it matters, here. ByteArrayXStream's close() doesn't do anything at all. The point is, it either does nothing in which case you should remove it, or if it does have an effect, your code would be broken).
myTestString.getBytes()
No, don't ever call that method. It gives you the bytes by decoding the characters into bytes using 'platform default encoding'. Who knows what that is.
} catch (IOException e) {
e.printStackTrace();
}
The correct 'I dunno' exception handler is throw new RuntimeException("unhandled", e);, not e.printStackTrace();. You get more info, and you get fewer WTFs (because yours will continue execution even though things are clearly wrong, which is a very bad idea).
but I cannot get the output of zipOut to write to a string
Yup. Strings aren't bytes, what you want is not possible at all. In any language. Some languages make it look like you can - those are bad languages, that conflate strings and byte arrays. Python decided to crash and burn and invent a whole new python (python2k -> python3k) to try to fix this, which goes to show. Boy that was a ton of pain and they suffered it to fix this oversight.
but I cannot get the output of zipOut to write to a string and then have the string write to a file and then via the OS open the zipfile. How can that be done?
So, replace all occurences of 'string' in that sentence with 'byte array' and all is peachy fine!
this is really what I was looking for:
public void zip() {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zipOut = new ZipOutputStream(baos);
ByteArrayInputStream bais = new ByteArrayInputStream(testString.getBytes());
System.out.println("testString " + testString + " testString.getBytes() " + testString.getBytes());
ZipEntry zipEntry = new ZipEntry("Results.xml");
zipOut.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while((length = bais.read(bytes)) >= 0 ) {
zipOut.write(bytes, 0, length);
}
zipOut.close();
bais.close();
baos.close();
byte[] zipBytes = baos.toByteArray();
// just a test to see if can be opened in the operating system
OutputStream os = new FileOutputStream(new File("c:/t/again.zip"));
os.write(zipBytes);
os.close();
} catch(IOException e) {
e.printStackTrace();
}
}

Stream<Object> to InputStream

How do i convert type
Stream<Object> into an InputStream? Currently, I get the iterator and loop through all of the data converting it to a byteArray and adding it to an inputStream:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
Iterator<MyType> myItr = MyObject.getStream().iterator();
while (myItr.hasNext()) {
oos.writeObject(myItr.next().toString()
.getBytes(StandardCharsets.UTF_8));
}
oos.flush();
oos.close();
InputStream is = new ByteArrayInputStream(bao.toByteArray());
What is the overhead of doing this though? If my stream contains a terabyte of data, wouldn't I be sucking a terabyte of data into memory? Is there any better way to achieve this?
You should be able to convert the OutputStream into an InputStream using a pipe:
PipedOutputStream pos = new PipedOutputStream();
InputStream is = new PipedInputStream(pos);
new Thread(() -> {
try (ObjectOutputStream oos = new ObjectOutputStream(pos)) {
Iterator<MyType> myItr = MyObject.getStream().iterator();
while (myItr.hasNext()) {
oos.writeObject(myItr.next().toString()
.getBytes(StandardCharsets.UTF_8));
}
} catch (IOException e) {
// handle closed pipe etc.
}
}).start();
Inspired by this answer.
Would this work for you?
https://gist.github.com/stephenhand/292cdd8bba7a452d83c51c00d9ef113c
It's an InputStream implementation that takes a Stream<byte[]> as input data. You just need to .map() your abitrary objects to byte arrays however you want each object to be represented as bytes.
It only calls a terminal operation on the Stream when the InputStream is read, pulling objects off the Stream as the consumer reads more of the InputStream so it never loads the whole set into memory

Port DeflaterInputStream functionality to .net

I am trying to port the following java code to .net:
private final byte[] zipLicense(byte lic[])
{
byte buf[];
ByteArrayInputStream bis;
DeflaterInputStream dis;
ByteArrayOutputStream bos;
buf = new byte[64];
bis = new ByteArrayInputStream(lic);
dis = new DeflaterInputStream(bis, new Deflater());
bos = new ByteArrayOutputStream();
byte abyte0[];
int len;
while((len = dis.read(buf)) > 0)
bos.write(buf, 0, len);
abyte0 = bos.toByteArray();
try
{
bis.close();
dis.close();
bos.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
return abyte0;
}
My best shot was this code in C#:
private byte[] zipLicense(byte[] lic)
{
var outputMemStream = new MemoryStream();
ZipOutputStream zipStream;
using (zipStream = new ZipOutputStream(outputMemStream))
{
zipStream.Write(lic, 0, lic.Length);
Debug.WriteLine(string.Format("Compressed bytes: {0}", outputMemStream.Length));
}
return outputMemStream.ToArray();
}
ZipOutputStream is a class from SharpZipLib
When I try to run the C# code, I get error on first attempt to write to zipStream
zipStream.Write(lic, 0, lic.Length);
The error states that I haven't provided "No entry". I see in examples that one can and probably should seciffy an entry string to a zip stream, but what java code puts as an entry then? Please help in porting this java functionality to .Net. Thanks!
The Java DeflaterInputStream is more like .NET's DeflateStream. That is, it's simply a compressed stream, without the directory index that a full .zip file would contain.
Try this:
private byte[] zipLicense(byte[] lic)
{
var outputMemStream = new MemoryStream();
using (DeflateStream stream =
new DeflateStream(outputMemStream, CompressionMode.Compress, true))
{
stream.Write(lic, 0, lic.Length);
}
Debug.WriteLine(string.Format("Compressed bytes: {0}", outputMemStream.Length));
return outputMemStream.ToArray();
}
Note that I've added a call to Flush(). Without this, the outputMemStream.Length property may not be current (i.e. not quite the full length of the resulting stream).
For what it's worth, .NET now has reasonably good .zip file support built-in (e.g. ZipArchive class). So if you do find yourself actually needing that some day, I would try to use that first rather than adding a third-party library to your deployment.

java socket download image

I have done some research, also checked answer on stackoverflow. However i just cant get my code right, please help. the code can run, but i cant get the image, it shows 0kb.
Socket socket = new Socket(addr, port);
byte [] buffer = new byte[1024];
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
writer.println("GET " + url.getFile() + " HTTP/1.0\r\n");
writer.println("HOST:" + url.getHost() + "\r\n");
writer.println("\r\n");
DataInputStream in = new DataInputStream(socket.getInputStream());
ByteArrayOutputStream out = new ByteArrayOutputStream();
int n = 0;
while (-1!=(n=in.read(buffer)))
{
out.write(buffer, 0, n);
}
out.close();
in.close();
byte[] response = out.toByteArray();
FileOutputStream fos = new FileOutputStream("0.jpeg");
fos.write(response);
fos.close();
}catch (Exception e){
System.out.println(e.toString());
}
Using raw sockets to perform an HTTP GET is much more complicated than necessary.
I recommend using an HTTP client like the one from Apache or you can use java.net.URLConnection. See How do I do a HTTP GET in Java? or Using java.net.URLConnection to fire and handle HTTP requests
Your code doesn't have any obvious flaws. If you're getting a zero length file, it's because you aren't sending anything.
BTW you don't need the ByteArrayOutputStream. You can write everything you read directly to the FileOutputStream. Saves both time and space.

Can I change the type of stream I'm using without closing and reopening the socket in Java?

I'm doing some socket programming in Java and I'd like to be able to change between using the ObjectOutputStream, the DataOutputStream, and the PrintWriter all within the same socket/connection. Is this possible and what is the best way to do it?
I've tried just creating both types of objects, for example ObjectOutputStream and DataOutputStream, but that doesn't seem to work.
The reason I want to switch between them is to, for example, send a text command "INFO" that signals I'm about to send an object with information or a command "DATA" signalling that I'm about to send data. Any advice on the best way to do this is appreciated.
You can only use one underlying stream type however you can get that data from anywhere.
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(s.getOutputStream()));
public static void writeObject(DataOutputStream dos, Serializable obj) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.close();
dos.writeUTF("OBJECT");
byte[] bytes = baos.toByteArray();
dos.writeInt(bytes.length);
dos.write(bytes);
dos.flush();
}
public static void writeBytes(DataOutputStream dos, byte[] bytes) {
dos.writeUTF("BYTES");
dos.writeInt(bytes.length);
dos.write(bytes);
dos.flush();
}
public static void writeText(DataOutputStream dos, String text) {
dos.writeUTF("TEXT");
dos.writeUTF(text);
dos.flush();
}
Why do you want the *Stream to convert to the *Writer.
You can do what you want to do with *Stream.
Socket s = new Socket();
DataOutputStream stream = new DataOutputStream( s.getOutputStream() );
byte[] bytes = "INFO".getBytes();
stream.write(bytes);
//....
bytes = "DATA".getBytes();
stream.write(bytes);

Categories

Resources