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.
Related
I built an application in java on android that sends the bytes of a .jpg file through a socket and an Asynchronous Server Socket in C# on windows that receives the bytes and writes them into a .jpg a file. The received file can't be open.
In the java application, which is the client, I used the folowing asynctask class executed on the onCreate:
class asyncTask extends AsyncTask<Void,Void,Void>{
#Override
protected Void doInBackground(Void... voids) {
try {
final File myFile = new File("//sdcard/DCIM/Camera/img1.jpg");
byte[] bytes = new byte[(int) myFile.length()];
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(myFile));
buf.read(bytes, 0, bytes.length);
s = new Socket(ip,3333);
OutputStream OS = s.getOutputStream();
OS.write(bytes, 0, bytes.length);
OS.flush();
s.close();
} catch (IOException e) {
Log.d("Error",e.toString());
e.printStackTrace();
}
return null;
}
}
And in the C# application I received the data and saved it to a file in the following async callback method that is called when data is received:
public static void ReadCallback(IAsyncResult ar)
{
Socket clientSocket = (Socket)ar.AsyncState;
int buffLength = clientSocket.EndReceive(ar);
Array.Resize(ref buffer, buffLength);
totaLength += buffLength;
buffer.CopyTo(allData, totaLength - 1);
if (buffLength == 0)
{
Array.Resize(ref allData, totaLength);
File.WriteAllBytes("C: /Users/fxavi/Desktop/img.jpg", allData);
Console.WriteLine(totaLength);
}
else
clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReadCallback), clientSocket);
}
buf.read(bytes, 0, bytes.length);
That will mostly not read the requested amount of bytes.length bytes.
Change that first to
int nread = buf.read(bytes, 0, bytes.length);
And compare nread to bytes.length and discover that they are not equal.
Further it is a bad idea to load a file completely in memory. Imagine you want to send a GB file.
Better make a loop where you read a chunck from the input stream and then write that chunck to the output stream.
I feel really stupid after finding the solution for this problem. Which is that totaLength += buffLength; should be executed before buffer.CopyTo(allData, totaLength); so that the buffer is copied to the right index.
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) {
}
I would like to use bufferedInputStream and bufferedOutputStream to copy large binary files from source file to destination file.
Here is my code:
byte[] buffer = new byte[1000];
try {
FileInputStream fis = new FileInputStream(args[0]);
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(args[1]);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int numBytes;
while ((numBytes = bis.read(buffer))!= -1)
{
bos.write(buffer);
}
//bos.flush();
//bos.write("\u001a");
System.out.println(args[0]+ " is successfully copied to "+args[1]);
bis.close();
bos.close();
} catch (IOException e)
{
e.printStackTrace();
}
I can successfully copy but then I use
cmp src dest
in the command line to compare two files.
The error message
cmp: EOF on files
appears. May I know where I was wrong?
This is the mistake:
bos.write(buffer);
You're writing out the whole buffer, even if you only read data into part of it. You should use:
bos.write(buffer, 0, numBytes);
I'd also suggest using try-with-resources if you're using Java 7 or later, or put the close calls in a finally block otherwise.
As Steffen notes, Files.copy is a simpler approach if that's available to you.
If you are using Java 8 try the Files.copy(Path source, Path target) method.
you need to close your FileOutputStream and FileInputStream
Also you can use FileChannel to copy like as follows
FileChannel from = new FileInputStream(sourceFile).getChannel();
FileChanngel to = new FileOutputStream(destFile).getChannel();
to.transferFrom(from, 0, from.size());
from.close();
to.close();
You could use IOUtils from apatch-commons library
I think copyLarge fucntion it that you need
I need a very simple function that allows me to read the first 1k bytes of a file through FTP. I want to use it in MATLAB to read the first lines and, according to some parameters, to download only files I really need eventually. I found some examples online that unfortunately do not work. Here I'm proposing the sample code where I'm trying to download one single file (I'm using the Apache libraries).
FTPClient client = new FTPClient();
FileOutputStream fos = null;
try {
client.connect("data.site.org");
// filename to be downloaded.
String filename = "filename.Z";
fos = new FileOutputStream(filename);
// Download file from FTP server
InputStream stream = client.retrieveFileStream("/pub/obs/2008/021/ab120210.08d.Z");
byte[] b = new byte[1024];
stream.read(b);
fos.write(b);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
client.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
the error is in stream which is returned empty. I know I'm passing the folder name in a wrong way, but I cannot understand how I have to do. I've tried in many way.
I've also tried with the URL's Java classes as:
URL url;
url = new URL("ftp://data.site.org/pub/obs/2008/021/ab120210.08d.Z");
URLConnection con = url.openConnection();
BufferedInputStream in =
new BufferedInputStream(con.getInputStream());
FileOutputStream out =
new FileOutputStream("C:\\filename.Z");
int i;
byte[] bytesIn = new byte[1024];
if ((i = in.read(bytesIn)) >= 0) {
out.write(bytesIn);
}
out.close();
in.close();
but it is giving an error when I'm closing the InputStream in!
I'm definitely stuck. Some comments about would be very useful!
Try this test
InputStream is = new URL("ftp://test:test#ftp.secureftp-test.com/bookstore.xml").openStream();
byte[] a = new byte[1000];
int n = is.read(a);
is.close();
System.out.println(new String(a, 0, n));
it definitely works
From my experience when you read bytes from a stream acquired from ftpClient.retrieveFileStream, for the first run it is not guarantied that you get your byte buffer filled up. However, either you should read the return value of stream.read(b); surrounded with a cycle based on it or use an advanced library to fill up the 1024 length byte[] buffer:
InputStream stream = null;
try {
// Download file from FTP server
stream = client.retrieveFileStream("/pub/obs/2008/021/ab120210.08d.Z");
byte[] b = new byte[1024];
IOUtils.read(stream, b); // will call periodically stream.read() until it fills up your buffer or reaches end-of-file
fos.write(b);
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(inputStream);
}
I cannot understand why it doesn't work. I found this link where they used the Apache library to read 4096 bytes each time. I read the first 1024 bytes and it works eventually, the only thing is that if completePendingCommand() is used, the program is held for ever. Thus I've removed it and everything works fine.
My application is unable to transfer data properly over a socket connection and write it to a file properly. Files over about 65,535 bytes get corrupted and are no longer recognized by the programs designed to run them.
I have been able to send small .doc and .txt files successfully, but .mp3 .wmv .m4a .avi and just about anything else does not work. Neither do larger docs.
I have looked all over the internet for a solution to this problem. I have repeatedly tweaked the I/O code to fix the problem but it still doesn't work! Here is the I/O code in the super class that handles sending and receiving files. If you need anymore information/other parts of code, let me know.
protected void sendFile() throws IOException {
byte[] bytes = new byte[(int) file.length()];
buffin = new BufferedInputStream(new FileInputStream(file));
int bytesRead = buffin.read(bytes,0,bytes.length);
System.out.println(bytesRead);
out = sock.getOutputStream();
out.write(bytes,0,fileBytes);
out.flush();
out.close();
}
protected void receiveFile() throws IOException {
byte[] bytes = new byte[fileBytes];
in = sock.getInputStream();
for(int i=0;i<fileBytes;i++) {
in.read(bytes);
}
fos = new FileOutputStream("/Datawire/"+fileName);
buffout = new BufferedOutputStream(fos);
buffout.write(bytes,0,fileBytes);
buffout.flush();
buffout.close();
}
UPDATED CODE (that works):
protected void sendFile() throws IOException {
if((file.length())<63000) {
byte[] bytes = new byte[(int)file.length()];
buffin = new BufferedInputStream(new FileInputStream(file));
buffin.read(bytes,0,bytes.length);
out = sock.getOutputStream();
out.write(bytes,0,bytes.length);
out.close();
} else {
byte[] bytes = new byte[32000];
buffin = new BufferedInputStream(new FileInputStream(file));
out = sock.getOutputStream();
int bytesRead;
while((bytesRead = buffin.read(bytes))>0) {
out.write(bytes,0,bytesRead);
}
out.close();
}
}
protected void receiveFile() throws IOException {
if(fileBytes<63000) {
byte[] bytes = new byte[32000];
in = sock.getInputStream();
System.out.println(in.available());
in.read(bytes,0,fileBytes);
fos = new FileOutputStream("/Datawire/"+fileName);
buffout = new BufferedOutputStream(fos);
buffout.write(bytes,0,bytes.length);
buffout.close();
} else {
byte[] bytes = new byte[16000];
in = sock.getInputStream();
fos = new FileOutputStream("/Datawire/"+fileName);
buffout = new BufferedOutputStream(fos);
int bytesRead;
while((bytesRead = in.read(bytes))>0) {
buffout.write(bytes,0,bytesRead);
}
buffout.close();
}
}
The issue is that you are sending only chunks of it. That is, you are only sending 64k of the file ever. If the file is ever larger then 64k the other end will never see it.
You want to continously read from the BufferedInputStream until the read() returns either less then the length or -1.
Your code is completely wrong. This is how to copy a stream in Java:
int count;
byte[] buffer = new byte[8192]; // more if you like but no need for it to be the entire file size
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
You should use this both when sending the file and when receiving the file. At present your sending method hopes that the entire file fits into memory; fits into INTEGER_MAX bytes; and is read in one chunk by the read method, without even checking the result. You can't assume any of those things. Your receive method is complete rubbish: it just keeps overwriting the same array, again without checking any read() results.
EDIT: Your revised code is just as bad, or worse. You are calling read() to check for EOS and then throwing that byte away, and then calling read() again and throwing away the read count it returns. You pointlessly have a different path for files < 64000, or 63000, or whatever it is, that has zero benefit except to give you two code paths to test, or possibly four, instead of one. The network only gives you 1460 bytes at a time at best anyway so what is the point? You already have (a) a BufferedInputStream with a default buffersize of 8192, and (b) my code that uses a byte[] buffer of any size you like. My code above works for any amount of data in two lines of executable code. Yours is 20. QED.
I suggest that you use some good library to read and write file contents as well as socket read/write. For example Apache Commons IO. If you insist on writig code yourself, do it smaller chunks rather than the whole file at once.
You have to consider that InputStream.read returns the number of bytes read which may be less than the total number of bytes in the file.
You would probably be better off just letting something like CopyUtils.copy take care of this for you.
You need to loop until bytesRead < 0. You need to make sure that fileBytes is => than the transferred file.
protected void receiveFile() throws IOException {
byte [] bytes = new byte [fileBytes];
InputStream is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream("/Datawire/"+fileName);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = is.read(bytes,0,bytes.length);
int current = bytesRead;
do {
bytesRead =
is.read(bytes, current, (bytes.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > -1);
bos.write(bytes, 0 , current);
bos.flush();
bos.close();
}