i am writing to ask for the proper solution for solving the following difficulties:
I am required to encode the file in Base64 format, and there is no way for me to make the file small, as a result, i will surely suffered from OutOfMemory Exception, that why i used Streaming approach for solving it.
After the file is encoded, i have decoded it immediately by code and also online-tools. The decoded content was found missing 2 bytes at the end of the file sometimes, but not always. It did affected further processing to the file.
Hope someone could help and may be caused by an idiot mistake. Still thanks.
Here is the Code:
FileOutputStream fout = new FileOutputStream(path + ".txt");
//this is for printing out the base64 content
FileInputStream fin = new FileInputStream(path);
System.out.println("File Size:" + path.getTotalSpace());
ByteArrayOutputStream os = new ByteArrayOutputStream();
Base64OutputStream base64out = new Base64OutputStream(os,Base64.NO_WRAP);
byte[] buffer = new byte[3 * 512];
int len = 0;
while ((len = fin.read(buffer)) >= 0) {
base64out.write(buffer, 0, len);
}
System.out.println("Encoded Size:" + os.size());
String result = new String(os.toByteArray(), "UTF-8");
fout.write(os.toByteArray());
fout.close();
base64out.close();
os.close();
fin.close();
return result;
Here is the solution that works in the case of using Base64OutputStream. I will explain some of them after code:
Here is the Code:
FileOutputStream fout = new FileOutputStream(path + ".txt");
FileInputStream fin = new FileInputStream(path);
System.out.println("File Size:" + path.length());
ByteArrayOutputStream os = new ByteArrayOutputStream();
Base64OutputStream base64out = new Base64OutputStream(os,Base64.NO_WRAP);
byte[] buffer = new byte[3 * 512];
int len = 0;
while ((len = fin.read(buffer)) >= 0) {
base64out.write(buffer, 0, len);
}
System.out.println("Encoded Size:" + os.size());
base64out.flush();
base64out.close();//this did the tricks. Please see explanation.
String result = new String(os.toByteArray(), "UTF-8");
fout.write(os.toByteArray());
fout.flush();
fout.close();
os.close();
fin.close();
return result;
Actually, after using the suggestion from Dawnkeeper by added flush(), i have moved one line of code only.
The tricks is did in the base64out.close() before processing any data. As closing the Base64OutputStream might write Ending Padding of Base64 to the Output.
I got my idea from org.apache.myfaces.trinidad.util.Base64OutputStream close() method. That's why i tried.
It might seems strange closing the OutputStream before data processing, but it only close Base64OutputStream but not ByteArrayOutputStream at the same time in this case. Therefore, the data could still retrieve from ByteArrayOutputStream.
Thanks Dawnkeeper efforts, and hope this question could helps other suffered in OutOfMemory Exception.
Your streams should be flushed before using them for other operations and before closing them:
FileOutputStream fout = new FileOutputStream(path + ".txt");
//this is for printing out the base64 content
FileInputStream fin = new FileInputStream(path);
System.out.println("File Size:" + path.length()); // path.getTotalSpace() is the filesystem size
ByteArrayOutputStream os = new ByteArrayOutputStream();
Base64OutputStream base64out = new Base64OutputStream(os,Base64.NO_WRAP);
byte[] buffer = new byte[3 * 512];
int len = 0;
while ((len = fin.read(buffer)) >= 0) {
base64out.write(buffer, 0, len);
}
System.out.println("Encoded Size:" + os.size());
base64out.write(System.lineSeparator().getBytes());
base64out.flush(); // to be sure that everything is in the byte array
String result = new String(os.toByteArray(), "UTF-8");
fout.write(os.toByteArray());
fout.flush(); // make sure everything is written
fout.close();
base64out.close();
os.close();
fin.close();
System.out.println("new File Size:" + new File(path + ".txt").length()); // prints out the size of the finished file
return result;
Related
I have a BLOB file which I have got from the DB team. I know that its a PDF document (I opened using Notepad++ and I could see the file name) and I need to convert the same using java. I have checked for few examples and I couldn't find any example where the BLOB file itself is taken as an input instead of taking directly from the DB (Resultset). Can anyone please give some pointers as to how I can accomplish this?
Thanks in advance!
I have tried below,
File file = new File("C:/Users/User1/Desktop/0LK54E33K1477e2MCEU25JV0G8MG418S007N45JU.BLOB0");
FileInputStream fis = new FileInputStream(file);
//System.out.println(file.exists() + "!!");
//InputStream in = resource.openStream();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
try {
for (int readNum; (readNum = fis.read(buf)) != -1;) {
bos.write(buf, 0, readNum); //no doubt here is 0
//Writes len bytes from the specified byte array starting at offset off to this byte array output stream.
System.out.println("read " + readNum + " bytes,");
}
} catch (IOException ex) {
//Logger.getLogger(genJpeg.class.getName()).log(Level.SEVERE, null, ex);
}
byte[] bytes = bos.toByteArray();
//below is the different part
File someFile = new File("C:/Users/User1/Desktop/Test.pdf");
FileOutputStream fos = new FileOutputStream(someFile);
fos.write(bytes);
fos.flush();
fos.close();
I am trying to create a simple server-client-program where the user can upload and download files. I have got the Sockets and Streams to work, and I can upload a file to the server. But whenever one file has been uploaded the Server-side seems to get stuck in the loop that reads the streams and forwards it to the Server-file.
Server Code:
InputStream in = clientSocket.getInputStream();
String filePath = "......."
+ op[1];
System.out.println(op[0] + ": " + filePath);
FileOutputStream out = new FileOutputStream(filePath);
byte[] bytes = new byte[16*1024];
int count;
while ((count = in.read(bytes)) > 0) {
out.write(bytes, 0, count);
}
Client Code:
String filePath = "...."
+ path;
System.out.println("Attempting: " + filePath);
dos = new DataOutputStream(serverSocket.getOutputStream());
fis = new FileInputStream(filePath);
byte[] buffer = new byte[4096];
while (fis.read(buffer) > 0) {
dos.write(buffer);
}
dos.flush();
fis.close();
The problem is that the program gets stuck at the while-loop, so the Server can not perform anything else. There are no errors or anything...
You never close the stream on the client side. Add dos.close() after dos.flush()!
I have a servlet to let user download a file from server. The original file is human readable, but the downloaded file alwyas contains binary content at the end of the file.
HttpSession session = request.getSession(true);
String fileName = session.getAttribute("download").toString();
System.out.println("Download file " + fileName);
File file = new File(fileName);
FileInputStream fileIn = new FileInputStream(file);
response.setContentType("text/plain");
response.setHeader("Content-Disposition", "attachment;filename=" + file.getName());
ServletOutputStream out = response.getOutputStream();
byte[] bytes = new byte[BYTES_DOWNLOAD];
while (fileIn.read(bytes, 0, BYTES_DOWNLOAD) != -1) {
out.write(bytes, 0, BYTES_DOWNLOAD);
}
out.flush();
out.close();
Thanks in advance.
Small bug in your code:
byte[] bytes = new byte[BYTES_DOWNLOAD];
int count;
while ( (count = fileIn.read(bytes)) != -1) {
out.write(bytes, 0, count);
}
What binary content do you see? Is it perhaps the line endings in the file, if any?
In TCP i am receiving media stream from an IP camera as RAW. According to there advise, i need to write that as file. And then i can play it with media player such as VLC.
But when i write this to a file, and play with media players it never play corrupted.
After comparing the original file i see my Java writing it in wrong characters. And there sample file shows different. What or how do i fix such file writing issue, here is how i am writing it:
byte[] buf=new byte[1024];
int bytes_read = 0;
try {
bytes_read = sock.getInputStream().read(buf, 0, buf.length);
String data = new String(buf, 0, bytes_read);
System.err.println("DATA: " + bytes_read + " bytes, data=" +data);
BufferedWriter out = new BufferedWriter(
new FileWriter("capture.ogg", true));
out.write(data);
out.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
You shouldn't use Readers, Writers and Strings for binary data. Stick with InputStreams and OutputStreams.
I.e., change
BufferedWriter -> BufferedOutputStream,
FileWriter -> FileOutputStream
and instead of String, just use a byte[].
If you're dealing with sockets, I must advice you to look into the NIO package though.
You're doing it right... at least until the part where you turn your byte[] into a String:
That step only really makes sense if your byte[] represents textual data in the first place! Which it doesn't!
Whenever you handle binary data or don't actually care what the data represents you must avoid using String/Reader/Writer to handle that data. Instead do use byte[]/InputStream/OutputStream.
Also, you must read from the socket in a loop, because nothing guarantees that you've read everything:
byte[] buf=new byte[1024];
int bytes_read;
OutputStream out = new FileOutputStream("capture.ogg", true);
InputStream in = sock.getInputStream();
while ((bytes_read = in.read(buf)) != -1) {
out.write(buf, 0, bytes_read);
}
out.close();
The way you have it written limits the output file to a maximum size of 1024 bytes. Try a loop:
try {
byte[] buf = new byte[1024];
int bytes_read = 0;
InputStream in = sock.getInputStream();
FileOutputStream out = new FileOutputStream(new File("capture.ogg"));
do {
bytes_read = in.read(buf, 0, buf.length);
System.out.println("Just Read: " + bytes_read + " bytes");
if (bytes_read < 0) {
/* Handle EOF however you want */
}
if (bytes_read > 0)
out.write(buf, 0, bytes_read);
} while (bytes_read >= 0);
out.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
From a DB2 table I've got blob which I'm converting to a byte array so I can work with it. I need to take the byte array and create a PDF out of it.
This is what I have:
static void byteArrayToFile(byte[] bArray) {
try {
// Create file
FileWriter fstream = new FileWriter("out.pdf");
BufferedWriter out = new BufferedWriter(fstream);
for (Byte b: bArray) {
out.write(b);
}
out.close();
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
But the PDF it creates is not right, it has a bunch of black lines running from top to bottom on it.
I was actually able to create the correct PDF by writing a web application using essentially the same process. The primary difference between the web application and the code about was this line:
response.setContentType("application/pdf");
So I know the byte array is a PDF and it can be done, but my code in byteArrayToFile won't create a clean PDF.
Any ideas on how I can make it work?
Sending your output through a FileWriter is corrupting it because the data is bytes, and FileWriters are for writing characters. All you need is:
OutputStream out = new FileOutputStream("out.pdf");
out.write(bArray);
out.close();
One can utilize the autoclosable interface that was introduced in java 7.
try (OutputStream out = new FileOutputStream("out.pdf")) {
out.write(bArray);
}
Read from file or string to bytearray.
byte[] filedata = null;
String content = new String(bytearray);
content = content.replace("\r", "").replace("\uf8ff", "").replace("'", "").replace("\"", "").replace("`", "");
String[] arrOfStr = content.split("\n");
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
try (PDPageContentStream cs = new PDPageContentStream(document, page)) {
// setting font family and font size
cs.beginText();
cs.setFont(PDType1Font.HELVETICA, 14);
cs.setNonStrokingColor(Color.BLACK);
cs.newLineAtOffset(20, 750);
for (String str: arrOfStr) {
cs.newLineAtOffset(0, -15);
cs.showText(str);
}
cs.newLine();
cs.endText();
}
document.save(znaFile);
document.close();
public static String getPDF() throws IOException {
File file = new File("give complete path of file which must be read");
FileInputStream stream = new FileInputStream(file);
byte[] buffer = new byte[8192];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int bytesRead;enter code here
while ((bytesRead = stream.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
System.out.println("it came back"+baos);
byte[] buffer1= baos.toByteArray();
String fileName = "give your filename with location";
//stream.close();
FileOutputStream outputStream =
new FileOutputStream(fileName);
outputStream.write(buffer1);
return fileName;
}