I want to archive some files that I am receiving from an external source. I receive each of this files as a ByteArrayInputStream. In the end I want my method to create the zip archive and return a byte[] array so that I can download it later.
I have successfully managed to do this, but the end result is an ZipOutputStream and not the byte[] array that I need.
Any ideeas are appreciated. Thanks!
FileOutputStream fos = null;
ZipOutputStream zipOut = null;
try {
fos = new FileOutputStream(archiveFileName.concat(ReportFormat.ZIP.getFileExtension()));
zipOut = new ZipOutputStream(new BufferedOutputStream(fos));
for (Map.Entry<?, ByteArrayInputStream> entry : mapInputStream.entrySet()) {
String fileFromInsiteArchiveName = (String) entry.getKey();
ByteArrayInputStream inputStream = entry.getValue();
ZipEntry zipEntry = new ZipEntry(fileFromInsiteArchiveName);
zipOut.putNextEntry(zipEntry);
byte[] tmp = new byte[4 * 1024];
int size = 0;
while ((size = inputStream.read(tmp)) != -1) {
zipOut.write(tmp, 0, size);
}
zipOut.flush();
inputStream.close();
}
zipOut.close();
return zipOut;
} catch (FileNotFoundException e) {
//handle this
} catch (IOException e) {
//handle this
} finally {
try {
if (fos != null) fos.close();
} catch (Exception ex) {
//handlethis
}
}
return zipOut;
}
Copy to ByteArrayOutputStream and then do baos.toByteArray() to get your byte[]
I want to put a textfile containing just one string into a tar archive and put this tar file into an inputstream... I want to do this "on the fly", without saving any temporary files to the disk...
I tried out this snippet, where I end up with a file:
FileOutputStream fos = null;
try {
fos = new FileOutputStream ("helloworld.txt");
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String config = "HelloWorld!";
byte[] b = config.getBytes();
try {
baos.write(b);
baos.writeTo(fos);
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
And I had a look at the jtar library:
https://code.google.com/p/jtar/
So I would like to put that textfile directly into that tar, but I also don't need that new FileOutputStream( "c:/test/test.tar" ), instead I want to put it into an inputstream directly.
I'm a bit confused with all those inputstreams/outputstreams and I'm not sure if it's even possible to move around a bunch of those streams instead of creating temporary files to do this.
THX & BR
Just get rid of the FileOutputStream and the bos.writeTo(), and do:
ByteArrayInputStream bais = new ByteArrayInputStream (baos.toByteArray());
instead.
I'm not sure if this is the best way to do it, but this seems to work, but not exactly as I imagined:
File tempFile = File.createTempFile("config", ".properties");
BufferedWriter bw = new BufferedWriter(new FileWriter(tempFile));
bw.write("Helloworld!!!!");
bw.close();
File tempTarFile = File.createTempFile("config", ".tar");
FileOutputStream dest = new FileOutputStream( tempTarFile );
TarOutputStream out = new TarOutputStream( new BufferedOutputStream( dest ) );
out.putNextEntry(new TarEntry(tempFile, "config.properties"));
BufferedInputStream origin = new BufferedInputStream(new FileInputStream( tempFile ));
int count;
byte data[] = new byte[2048];
while((count = origin.read(data)) != -1) {
out.write(data, 0, count);
}
out.flush();
origin.close();
out.close();
tempFile.delete();
tempTarFile.delete();
InputStream inputStream = new FileInputStream(tempTarFile);
//to check if it worked:
// OutputStream outputStream = null;
//
// try {
//
// // write the inputStream to a FileOutputStream
// outputStream =
// new FileOutputStream(new File("config.tar"));
//
// int read = 0;
// byte[] bytes = new byte[1024];
//
// while ((read = inputStream.read(bytes)) != -1) {
// outputStream.write(bytes, 0, read);
// }
//
// System.out.println("Done!");
//
// } catch (IOException e) {
// e.printStackTrace();
// } finally {
// if (inputStream != null) {
// try {
// inputStream.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// if (outputStream != null) {
// try {
// // outputStream.flush();
// outputStream.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
//
// }
// }
I'm trying to compress the byte data from video, the app crashes when the file is over 10mb due to the limitations of Parse servers. So I'm trying to compress at 10mb. The code does well on older phones but on the newer phones the the video bytes easily go over 10mb but the code won't compress the bytes down to 10 mb. Is there something I can add or something?
private void uploadVideo() {
Intent videoIntent = new Intent (MediaStore.ACTION_VIDEO_CAPTURE);
mMediaUri = getOutputMediaFileUri (MEDIA_TYPE_VIDEO);
if (mMediaUri == null) {
// display an error
Toast.makeText (MemberActivity.this, R.string.error_external_storage,
Toast.LENGTH_LONG).show ();
} else {
videoIntent.putExtra (MediaStore.EXTRA_OUTPUT, mMediaUri);
videoIntent.putExtra (MediaStore.EXTRA_DURATION_LIMIT, 10);
videoIntent.putExtra (MediaStore.EXTRA_SIZE_LIMIT, 1024*1024*10);
videoIntent.putExtra (MediaStore.EXTRA_VIDEO_QUALITY, 0); // 0 = lowest res
startActivityForResult (videoIntent, CAMERA_CAPTURE_VIDEO_REQUEST_CODE);
}
String mediaBytes = mMediaUri.getEncodedPath ();
//Set up video file and data
File iFile = new File (mediaBytes);
byte[] byteArray = new byte[(int) iFile.length ()];
try {
FileInputStream fileInputStream = new FileInputStream (iFile);
fileInputStream.read (byteArray);
for (byte aByteArray : byteArray) {
System.out.print ((char) aByteArray);
}
} catch (FileNotFoundException e) {
System.out.println ("File Not Found.");
e.printStackTrace ();
} catch (IOException e1) {
System.out.println ("Error Reading The File.");
e1.printStackTrace ();
}
final ParseFile file = new ParseFile ("HipkuVideo.mp4", byteArray);
file.saveInBackground (new SaveCallback () {
#Override
public void done(ParseException e) {
if (e == null) {
//addPhotoTransferToUserUpload (file);
// Show a simple toast message
Toast.makeText (MemberActivity.this, "Saving to SD Card",
Toast.LENGTH_SHORT).show ();
} else {
// Show a simple toast message
Toast.makeText (MemberActivity.this, "Error saving:" + e.getMessage (),
Toast.LENGTH_SHORT).show ();
}
and here is the compress code:
public static byte[] getByteArrayFromFile(Context context, Uri uri) {
byte[] fileBytes = null;
InputStream inStream = null;
ByteArrayOutputStream outStream = null;
if (uri.getScheme().equals("content")) {
try {
inStream = context.getContentResolver().openInputStream(uri);
outStream = new ByteArrayOutputStream();
// Compressor with highest level of compression
Deflater compressor = new Deflater();
compressor.setLevel(Deflater.BEST_COMPRESSION);
// Give the compressor the data to compress
compressor.setInput(fileBytes);
compressor.finish();
// Create an expandable byte array to hold the compressed data.
// It is not necessary that the compressed data will be smaller than
// the uncompressed data.
outStream = new ByteArrayOutputStream(fileBytes.length);
// Compress the data
byte[] buf = new byte[1024*1024*10];
while (!compressor.finished()) {
int count = compressor.deflate(buf);
outStream.write(buf, 0, count);
}
try {
outStream.close();
} catch (IOException e) {
}
// Get the compressed data
byte[] compressedData = outStream.toByteArray();
byte[] bytesFromFile = new byte[1024]; // buffer size (1 MB)
int bytesRead = inStream.read(compressedData);
while (bytesRead != -1) {
outStream.write(compressedData, 0, bytesRead);
bytesRead = inStream.read(compressedData);
}
fileBytes = outStream.toByteArray();
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
}
finally {
try {
inStream.close();
outStream.close();
}
catch (IOException e) { /*( Intentionally blank */ }
}
}
else {
try {
File file = new File(uri.getPath());
FileInputStream fileInput = new FileInputStream(file);
fileBytes = IOUtils.toByteArray(fileInput);
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}
return fileBytes;
}
If you need to compress further than what's provided by ZLIB, take a look at Apache Commons Compress. Specifically, the section on XZ since that uses the LZMA compression algorithm which at it's highest level gives some of the best compression ratios around. Be sure to thoroughly test performance however since it can get a little slow. If you're worried about space you can cut out the Apache middleman and go straight to the Tukaani java library for the same.
In my Java program, I would like to display the progress of moving a file. I use the following snippet of code to copy files, which allows me to track the bytes copied and shows it in a progress bar. I was wondering if the code code be adapted to move files rather than just copy them?
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetFile));
int theByte;
while((theByte = bis.read()) != -1)
{
bos.write(theByte);
}
bis.close();
bos.close();
Okay, so a "move" operation is a copy with a "delete" at the end, for example...
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(sourceFile));
bos = new BufferedOutputStream(new FileOutputStream(targetFile));
int theByte;
while((theByte = bis.read()) != -1)
{
bos.write(theByte);
}
bos.close();
bis.close();
// You may want to verify that the file's are the same (ie the file size for example)
if (!sourceFile.delete()) {
throw new IOException("Failed to remove source file " + sourceFile);
}
} catch (IOException exp) {
exp.printStackTrace();
} finally {
try {
bis.close();
} catch (Exception exp) {
}
try {
bos.close();
} catch (Exception exp) {
}
}
I am trying to get file content in bytes in Android application. I have get the file in SD card now want to get the selected file in bytes. I googled but no such success. Please help
Below is the code to get files with extension. Through this i get files and show in spinner. On file selection I want to get file in bytes.
private List<String> getListOfFiles(String path) {
File files = new File(path);
FileFilter filter = new FileFilter() {
private final List<String> exts = Arrays.asList("jpeg", "jpg", "png", "bmp", "gif","mp3");
public boolean accept(File pathname) {
String ext;
String path = pathname.getPath();
ext = path.substring(path.lastIndexOf(".") + 1);
return exts.contains(ext);
}
};
final File [] filesFound = files.listFiles(filter);
List<String> list = new ArrayList<String>();
if (filesFound != null && filesFound.length > 0) {
for (File file : filesFound) {
list.add(file.getName());
}
}
return list;
}
here it's a simple:
File file = new File(path);
int size = (int) file.length();
byte[] bytes = new byte[size];
try {
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file));
buf.read(bytes, 0, bytes.length);
buf.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Add permission in manifest.xml:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
The easiest solution today is to used Apache common io :
http://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/FileUtils.html#readFileToByteArray(java.io.File)
byte bytes[] = FileUtils.readFileToByteArray(photoFile)
The only drawback is to add this dependency in your build.gradle app :
implementation 'commons-io:commons-io:2.5'
+ 1562 Methods count
Since the accepted BufferedInputStream#read isn't guaranteed to read everything, rather than keeping track of the buffer sizes myself, I used this approach:
byte bytes[] = new byte[(int) file.length()];
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
DataInputStream dis = new DataInputStream(bis);
dis.readFully(bytes);
Blocks until a full read is complete, and doesn't require extra imports.
Here is a solution that guarantees entire file will be read, that requires no libraries and is efficient:
byte[] fullyReadFileToBytes(File f) throws IOException {
int size = (int) f.length();
byte bytes[] = new byte[size];
byte tmpBuff[] = new byte[size];
FileInputStream fis= new FileInputStream(f);;
try {
int read = fis.read(bytes, 0, size);
if (read < size) {
int remain = size - read;
while (remain > 0) {
read = fis.read(tmpBuff, 0, remain);
System.arraycopy(tmpBuff, 0, bytes, size - remain, read);
remain -= read;
}
}
} catch (IOException e){
throw e;
} finally {
fis.close();
}
return bytes;
}
NOTE: it assumes file size is less than MAX_INT bytes, you can add handling for that if you want.
If you want to use a the openFileInput method from a Context for this, you can use the following code.
This will create a BufferArrayOutputStream and append each byte as it's read from the file to it.
/**
* <p>
* Creates a InputStream for a file using the specified Context
* and returns the Bytes read from the file.
* </p>
*
* #param context The context to use.
* #param file The file to read from.
* #return The array of bytes read from the file, or null if no file was found.
*/
public static byte[] read(Context context, String file) throws IOException {
byte[] ret = null;
if (context != null) {
try {
InputStream inputStream = context.openFileInput(file);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int nextByte = inputStream.read();
while (nextByte != -1) {
outputStream.write(nextByte);
nextByte = inputStream.read();
}
ret = outputStream.toByteArray();
} catch (FileNotFoundException ignored) { }
}
return ret;
}
In Kotlin you can simply use:
File(path).readBytes()
You can also do it this way:
byte[] getBytes (File file)
{
FileInputStream input = null;
if (file.exists()) try
{
input = new FileInputStream (file);
int len = (int) file.length();
byte[] data = new byte[len];
int count, total = 0;
while ((count = input.read (data, total, len - total)) > 0) total += count;
return data;
}
catch (Exception ex)
{
ex.printStackTrace();
}
finally
{
if (input != null) try
{
input.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
return null;
}
A simple InputStream will do
byte[] fileToBytes(File file){
byte[] bytes = new byte[0];
try(FileInputStream inputStream = new FileInputStream(file)) {
bytes = new byte[inputStream.available()];
//noinspection ResultOfMethodCallIgnored
inputStream.read(bytes);
} catch (IOException e) {
e.printStackTrace();
}
return bytes;
}
Following is the working solution to read the entire file in chunks and its efficient solution to read the large files using a scanner class.
try {
FileInputStream fiStream = new FileInputStream(inputFile_name);
Scanner sc = null;
try {
sc = new Scanner(fiStream);
while (sc.hasNextLine()) {
String line = sc.nextLine();
byte[] buf = line.getBytes();
}
} finally {
if (fiStream != null) {
fiStream.close();
}
if (sc != null) {
sc.close();
}
}
}catch (Exception e){
Log.e(TAG, "Exception: " + e.toString());
}
To read a file in bytes, often used to read binary files, such as pictures, sounds, images, etc.
Use the method below.
public static byte[] readFileByBytes(File file) {
byte[] tempBuf = new byte[100];
int byteRead;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
while ((byteRead = bufferedInputStream.read(tempBuf)) != -1) {
byteArrayOutputStream.write(tempBuf, 0, byteRead);
}
bufferedInputStream.close();
return byteArrayOutputStream.toByteArray();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}