Build multipart/form-data using Java and without Apache libraries - java

I have a java code that builds a multipart/form-data and it all works OK but when the text part is in cyrilic it becomes unreadable on the server side.
The reason this happens is because the DataOutputStream class doesn't handle cyrilic character except if i use its method .writeUTF but then two additional bytes are added the again this makes me some trouble on the server side.
Here is the beggining of the code:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
Then the text bytes and image bytes are written to the dos object and finally we have
bos.toByteArray();
Do you know what else i can use instead of DataOutputStream and ByteArrayOutputStream.

DataOutputStream has no proper way to write Strings in specified encoding, but if you can't switch to e.g. BufferedWriter/OutputStreamWriter, you can use the write(byte[] b, int offset, int len) as follows:
byte[] bytes = myString.getBytes("UTF-8"); // or whichever encoding you want
dataout.write(bytes, 0, bytes.length);

Related

Java: I need to get byte array out of outputstream

In my case the out put stream is basically FileOutputStream. Hence for this code:
ByteArrayOutputStream bos = (ByteArrayOutputStream) streamToEncrypt;
(Where streamToEncrypt is OutputStream) is getting this exception:
java.lang.ClassCastException: java.io.FileOutputStream cannot be cast to java.io.ByteArrayOutputStream
All I need to do is to get the byte array out of this outputstream.
I do NOT have access to the file at this level. All I have is this output stream that I have to encrypt before pushing it to the file
That simply doesn't make any sense.
A ByteArrayOutputStream takes the data you push into it ... and stores them within a byte array that you can retrieve later on.
A FileOutputStream takes data ... and pushes it into a file.
Those are two completely different classes; you simply can't cast one into the other! Thats like you trying to cast a String into an Integer; or turning an Apple into a Banana by saying "you apple, now be a banana". Simply wont work!
So, the real "answer" here: you should step back and clarify what exactly you intend to do with your data; and then you use that stream(s) matching that requirement(s).
You don't get bytes out of an OutputStream. You get them out of an InputStream. You put bytes into an OutputStream.
If bytes have already been written to the OutputStream, it's too late. Opening the file again and reading from it is the only way for you to access those data.
If you want to encrypt an output stream, you should construct the stream and pass it to the code that writes to the stream.
Cipher enc = Cipher.getInstance("...");
enc.init(...);
try (OutputStream fos = Files.newOutputStream(path);
OutputStream os = new CipherOutputStream(fos, enc)) {
writingObject.write(os);
}

JAVA: Stream any file to browser correctly

So I have created my own personal HTTP Server in Java from scratch.
So far it is working fine but with one major flaw.
When I try to pass big files to the browser I get a Java Heap Space error. I know how to fix this error through the JVM but I am looking for the long term solution for this.
//declare an integer for the byte length of the file
int length = (int) f.length();
//start the fileinput stream.
FileInputStream fis = new FileInputStream(f);
//byte array with the length of the file
byte[] bytes = new byte[length];
//write the file until the bytes is empty.
while ((length = fis.read(bytes)) != -1 ){
write(bytes, 0, length);
}
flush();
//close the file input stream
fis.close();
This way sends the file to the browser successfully and streams it perfectly but the issue is, because I am creating a byte array with the length of the file. When the file is very big I get the Heap Space error.
I have eliminated this issue by using a buffer as shown below and I dont get Heap Space errors anymore. BUT the way shown below does not stream the files in the browser correctly. It's as if the file bytes are being shuffled and are being sent to the browser all together.
final int bufferSize = 4096;
byte buffer[] = new byte[bufferSize];
FileInputStream fis = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(fis);
while ( true )
{
int length = bis.read( buffer, 0, bufferSize );
if ( length < 0 ) break;
write( buffer, 0, length );
}
flush();
bis.close();
fis.close();
NOTE1:
All the correct Response Headers are being sent perfectly to the browser.
Note2:
Both ways work perfectly on a computer browser but only the first way works on a smartphone's browser (but sometimes it gives me Heap Space error).
If someone knows how to correctly send files to a browser and stream them correctly I would be a very very happy man.
Thank you in advance! :)
When reading from a BufferedInputStream you can allow its' buffer to handle the buffering, there is no reason to read everything into a byte[] (and certainly not a byte[] of the entire File). Read one byte at a time, and rely on the internal buffer of the stream. Something like,
FileInputStream fis = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(fis);
int abyte;
while ((abyte = bis.read()) != -1 ){
write(abyte);
}
Emm... As I can see it, you try to use chunks in your code anyway,
as I can remember, even the apache HttpClient+FileUpload solution has file size limit about <=2.1GB or something (correct me if I am wrong) so it is a bit hard thing...
I haven't tried the solution yet but as a test you can use java.io.RandomAccessFile in combination with File(Input/Output)Stream on the client and server not to read and write the whole file at a time but sequence of lets say <=30MB blocks for example to avoid the annoying outofmemory errors ; An example of using RandomAccessFile can be found here https://examples.javacodegeeks.com/core-java/io/randomaccessfile/java-randomaccessfile-example/
But still you give less details :( I mean is your client suppose to be a common Java application or not?
If you have some additional information please let me know
Good luck :)

java Files.readAllBytes(image.png) doesn't work

I was trying to read from file and then write to other file. I use code bellow to do so.
byte[] bytes = Files.readAllBytes(file1);
Writer Writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file2), "UTF-8"));
for(int i=0;i<bytes.length;i++)
Writer.write(bytes[i]);
Writer.close();
But when I change file1 to picture.png and file2 to picture2.png, this method doesn't work and I can't open picture2.png using image viewer.
What have I done wrong?
Writers are for writing text, possibly in different formats (ie utf-8 / 16, etc). For writing raw bytes, don't use writers. Just use (File)OutputStreams.
It is truly as simple as
byte[] bytes = ...;
FileOutputStream fos = ...;
fos.write(bytes);
The other answers explain why what you have potentially fails.
I'm curious why you're already using one Java NIO method, but not others? The library already has methods to do this for you.
byte[] bytes = Files.readAllBytes(file1);
Files.write(file2, bytes, StandardOpenOption.CREATE_NEW); // or relevant OpenOptions
or
FileOutputStream out = new FileOutputStream(file2); // or buffered
Files.copy(file1, out);
out.close();
or
Files.copy(file1, file2, options);
The problem is that Writer.write() doesn't take a byte. It takes a char, which is variable size, and often bigger than one byte.
But once you've got the whole thing read in as a byte[], you can just use Files.write() to send the whole array to a file in much the same way that you read it in:
Files.write(filename, bytes);
This is the more modern NIO idiom, rather than using an OutputStream.
It's worth reading the tutorial.

Files not copying correctly with Java

I have written a little program that just reads a files contents and writes it to a new copy. This works perfectly with text files, but with PNGs and video files, it fails to correctly create the file (the image is all black or the video will not play). I know there are APIs that can copy files with one line, but I'd love to know why this isn't working. Here is the code:
import java.io.*;
public class CopyFile
{
public static void main(String[] args) throws Exception
{
File file = new File("test.mp4");
File copy = new File("copy.mp4");
InputStreamReader input = new InputStreamReader(new FileInputStream(file));
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(copy));
System.out.println(input.ready());
while(input.ready())
{
int i = input.read();
//System.out.print( (char) ( (byte) i));
out.write(i);
}
input.close();
out.flush();
out.close();
}
}
Don't use Reader and Writer unless you know the input is text. Use InputStream and OutputStream.
Don't use ready(), or, for Sotirios' benefit, available() either. Neither of them is a valid test for end of stream. They both concern whether the input can be read without blocking, which isn't the same thing at all. See the Javadoc.
You're not detecting end of stream correctly. If read() returns -1 you're still copying that to the output.
Copying a single character or single byte at a time is extremely slow.
The canonical way to copy streams in Java is as follows:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
where count is an int, and buffer is a byte[] of any size greater than zero, typically 8192.
Readers and Writers are for reading character streams (i.e., text). Pictures and videos are binary data, not text, and will probably be corrupted if you pass them through character streams. This is because, depending on the character set, there is not necessarily a reversible mapping between bytes and characters. Some byte sequences are gibberish if interpreted as characters, then gibberish gets written back to the file.
Use the InputStream and OutputStream that you open directly, instead of wrapping them up as a Reader and Writer, and it will work correctly. These are byte streams and can handle any type of data.
E.g.,
InputStream input = new FileInputStream(file);
OutputStream out = new FileOutputStream(copy);
P.S. This will still be quite slow. You can wrap the streams in a BufferedInputStream and BufferedOutputStream for a simple way to improve performance, although the one-line copy APIs will probably still be faster.

change byte[] to inputstream?

I'm using two libraries in an android app I'm trying to make. New to android. The app is for connecting to serial devices and controlling their console via a terminal.
One library is for setting up a serial connection, setting baud rate etc. and can also write read/data over serial.. The other is for creating a terminal session. My problem lies in incorporating both of these together to have a terminal that is connected to a serial device.
In the terminal library I need to supply an InputStream and OutputStream to provide input and output to the terminal. So I have to call setTermIn(java.io.InputStream) and setTermOut(java.io.OutputStream) to connect the input and output streams to the emulator.
In the serial library however there are two methods for sending and receiving and these deal with arrays of bytes.
sendData(byte[] data) for sending data and a dataListener for receiving data. I have to implement this and code the method onDataReceived(int id, byte[] data) with id being the name of the device.
I don't have source code for the function that sends an array of bytes over serial, so how do I make the array of bytes into a stream to send to my terminal?
EDIT:
I think this should override it and that is what I want?
Private USB2SerialAdapter mSelectedAdapter;
...
public void sendData(byte[] data)
{
//this should echo what I send to the terminal in the correct format
ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length);
bos.write(data, 0, data.length);
setTermOut(bos);
//send data over serial using original sendData() method
mSelectedAdapter.sendData(data);
}
These two snippets should give you enough information to find a solution to your problem.
reading:
byte[] source = ...;
ByteArrayInputStream bis = new ByteArrayInputStream(source);
// read bytes from bis ...
writing
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// write bytes to bos ...
byte[] sink = bos.toByteArray();
This should do it: ByteArrayInputStream, ByteArrayOutputStream
Just look at the docs in those cases.

Categories