Convert byte array to playable mp4 file - java

I need to do some processing on the raw file bytes and the algorithm is fine with working on .wav file but the problem is the .mp4 files it is not playable at all.
I think the problem that the file contains raw bytes only and no header
please help me
public void convert(String maskFlag, File endFile)
{
byte[] rawData = getarr(originalFile);
byte[] effectedData = rawData.clone();
effectedData = changePitch(rawData, parameters.getPitch());
effectedData = changeVolume(effectedData, parameters.getVolume());
effectedData = changeSpeed(effectedData, parameters.getSpeed());
FileOutputStream out = new FileOutputStream(endFile);
out.write(effectedData);
out.close();
}
byte[] getarr(File file) throws Exception
{
InputStream fis = new FileInputStream(file);
fis = new FileInputStream(file);
byte [] byteArr = IOUtils.toByteArray(fis);
return byteArr;
}

Related

How to read n base64 encoded characters from a file at a time and decode and write to another file?

Currently I have a source file which has base64 encoded data (20 mb in size approx). I want to read from this file, decode the data and write to a .TIF output file. However I don't want to decode all 20MB data at once. I want to read a specific number of characters/bytes from the source file, decode it and write to destination file. I understand that the size of the data I read from the source file has to be in multiples of 4 or else it can't be decoded?
Below is my current code where I decode it all at once
public write Output(File file){
BufferedReader br = new BufferedReader (new Filereader(file));
String builder sb = new StringBuilder ();
String line=BR.readLine();
While(line!=null){
....
//Read line by line and append to sb
}
byte[] decoded = Base64.getMimeDecoder().decode(SB.toString());
File outputFile = new File ("output.tif")
OutputStream out = new BufferedOutputStream(new FileOutputStream(outputFile));
out.write(decoded);
out.flush();
}
How can I read specific number of characters from source file and decode and then write to output file so I don't have to load everything in memory?
Here is a simple method to demonstrate doing this, by wrapping the Base64 Decoder around an input stream and reading into an appropriately sized byte array.
public static void readBase64File(File inputFile, File outputFile, int chunkSize) throws IOException {
FileInputStream fin = new FileInputStream(inputFile);
FileOutputStream fout = new FileOutputStream(outputFile);
InputStream base64Stream = Base64.getMimeDecoder().wrap(fin);
byte[] chunk = new byte[chunkSize];
int read;
while ((read = base64Stream.read(chunk)) != -1) {
fout.write(chunk, 0, read);
}
fin.close();
fout.close();
}

Extract the zip and convert to base 64 of each file

I am reading the list of attachment from a system witch returns the attached document in base 64 encoded string as a zip and My objective is to get the base 64 encoded string for each attached document.
Note:- I am trying below code where I am unzipping the zip and writing at my local file system.
. But in real I wanted to get the base 64 format for each file without writing the file in local file system.
public class UnzipUtility {
private static final int BUFFER_SIZE = 4096;
private static void extractFile(ZipInputStream zipIn, ZipEntry entry) throws IOException {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:/Project/"+File.separator+entry.getName()));
byte[] bytesIn = new byte[BUFFER_SIZE];
System.out.println("File Name "+entry.getName());
int read = 0;
while ((read = zipIn.read(bytesIn)) != -1) {
//Hear I dont not want to write the output stream insted I want to get the base64 data for each file.
bos.write(bytesIn);
}
bos.close();
}
public static void main(String[] args) throws IOException {
String attachmentVariable="zip base 64 data"
byte[] bytedata = attachmentVariable.getBytes("UTF-8");
byte[] valueDecoded = Base64.decodeBase64(bytedata);
ZipInputStream zipIn = new ZipInputStream(new ByteArrayInputStream(valueDecoded));
ZipEntry entry = zipIn.getNextEntry();
// iterates over entries in the zip file
while (entry != null) { extractFile(zipIn,entry);
zipIn.closeEntry();
entry = zipIn.getNextEntry();
}
}
}
So, you have a Base64 encoded string with a zip file, and you want a Map<String, String>, where key is zip entry name and value is the Base64 encoded content.
In Java 9+, that is easily done like this:
String base64ZipFile = "zip base 64 data";
Map<String, String> base64Entries = new LinkedHashMap<>();
try (ZipInputStream zipIn = new ZipInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(base64ZipFile)))) {
Encoder encoder = Base64.getEncoder();
for (ZipEntry entry; (entry = zipIn.getNextEntry()) != null; ) {
base64Entries.put(entry.getName(), encoder.encodeToString(zipIn.readAllBytes()));
}
}
To Base64 encode data as it is being written to an OutputStream, use the Encoder.wrap(OutputStream os) method.
By default, BufferedOutputStream will use a 8192-byte buffer, so if you increase BUFFER_SIZE to 8192, then you won't need the BufferedOutputStream.
You should use try-with-resources, and the newer NIO.2 API.
Which means your code should be:
private static final int BUFFER_SIZE = 8192;
private static void extractFile(ZipInputStream zipIn, ZipEntry entry) throws IOException {
try ( OutputStream fos = Files.newOutputStream(Paths.get("D:/Project", entry.getName()));
OutputStream b64os = Base64.getEncoder().wrap(fos); ) {
System.out.println("File Name " + entry.getName());
byte[] buf = new byte[BUFFER_SIZE];
for (int len = 0; (len = zipIn.read(buf)) != -1; ) {
b64os.write(buf, 0, len);
}
}
}

How to convert base64 to different kind of files ( doc , pdf , word ..etc ) ?

I am working on project where I have to download attachments that i receive from server. I have to exploit base64 data and convert it to the appropriate type and download it. It works for me perfectly with images ( base 64 => bytes => bitmap ) but I find troubles with other types ( txt , pdf ..etc )
try this
try {
File sdcard = Environment.getExternalStorageDirectory();
File file = new File(sdcard,"test.pdf");
File new_file_name = new File(sdcard,"new_file.pdf");
byte[] input_file = IOUtil.readFile(file);
byte[] encodedBytes = Base64.encode(input_file,URL_SAFE);
String encodedString = new String(encodedBytes);
byte[] decodedBytes = Base64.decode(encodedString.getBytes(),URL_SAFE);
FileOutputStream fos = new FileOutputStream(new_file_name);
fos.write(decodedBytes);
fos.flush();
fos.close();
}catch (Exception e)
{
Log.e("ERROR",e.toString());
}
And IOUtil class
public class IOUtil {
public static byte[] readFile(String file) throws IOException {
return readFile(new File(file));
}
public static byte[] readFile(File file) throws IOException {
// Open file
RandomAccessFile f = new RandomAccessFile(file, "r");
try {
// Get and check length
long longlength = f.length();
int length = (int) longlength;
if (length != longlength)
throw new IOException("File size >= 2 GB");
// Read file and return data
byte[] data = new byte[length];
f.readFully(data);
return data;
} finally {
f.close();
}
}
}
this code contain both encode and decode parts

Storing Byte Array inside an Object, and then converting it to ObjectOutputStream? (Stuck)

I'm kind of stuck with this problem.
I have this FileDetails class which stores details/metadata of the file along with
the complete file in a byte array. I want to send the FileDetails object inside ObjectOutputStream across network, where the receiver will
simple read the file and cast it back to FileDetails.
Here is the code:
class FileDetails {
private String fileName;
private long fileSize;
private byte[] fileData;
public FileDetails(String fileName, long fileSize, byte[] fileData) {
this.fileName = fileName;
this.fileSize = fileSize;
this.fileData = fileData;
}
public String getFileName() {
return fileName;
}
public long getFileSize() {
return fileSize;
}
public byte[] getFileData() {
return fileData;
}
}
File file = new File("C://test.dat");
RandomAccessFile randFileAccess = new RandomAccessFile(file, "r");
byte[] buff = new byte[(int) file.length()];
randFileAccess.readFully(buff);
FileDetails fd = new FileDetails(file.getname(), file.length(); buff);
FileOutputStream fos = = new FileOutputStream(C://oos.dat);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(fd);
oos.write(buff);
The problem is that the file "test.dat" is quite large and it's not optimal to read it fully into the buffer(very large) in one go. I could have read the
file into the buffer in chunks, but that would require me to create file and save data into the disk, which I cannot do as FileDetails object takes byte array.
How can I solve this problem? I want this approach only, i.e. Storing data as byte array in FileDetails object and then converting it to ObjectOutputStream, because I will be appending
the appending an mp3 file infornt of the ObjectOutStream file and sending it over the internet.
Any suggetions? Or alternative approach?
Edit: Actually I am developing an android app. Where it stores the metadata of the file in a FileDetails object along with the file data in byte array.
This FileDetails object is converted into an ObjectOutputStream file. Now an a specific mp3 file is appended in front of this ObjectOutputStream file, which is used to recognize that the file has been sent by my app.
This combined mp3 file (which contains "hidden" ObjectOutputStream file) is send via a "popular" message app to the receiver.
The receiver downloads the mp3 file through his "popular" message app. Now my app comes into action. It recognizes the mp3 file. And extracts the ObjectOutputStream file from the mp3 file. And casts it back to FileDetails and retrieves the Original file with it's metadata.
Is my approach correct? Is there any other way to recognize my appended/hidden file?
Thanks a lot in advance.
Is it possible to add the class to the receiver?
Then you could try something like this:
File file = new File("C://test.dat")
InputStream in = null;
try {
in = new BufferedInputStream(new FileInputStream(file));
-> send over the network
finally {
if (in != null) {
in.close();
}
}
}
the receiver could just write the byte to a temporary file (and not hold them in memory)
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream("C://test.dat");
BufferedOutputStream bos = new BufferedOutputStream(fos);
//something like:
byte[] buffer = new byte[1024];
int len = is.read(buffer);
while (len != -1) {
bos.write(buffer, 0, len);
len = is.read(buffer);
}
and if the operation is finished, instantiate the object FileDetails fd = new FileDetails(the file you just created,....)
You can also send the class definition over network, if you must.
Here I've added read/writeObject methods:
class FileDetails implements Serializable {
private static final int CHUNK_LEN = 0x10000; // 64k
private String fileName;
private long fileSize;
private File file;
// Note: everything can be deduced from a File object
public FileDetails(File file) {
this.fileName = file.getName();
this.fileSize = file.length();
this.file = file;
}
public String getFileName() {
return fileName;
}
public long getFileSize() {
return fileSize;
}
// explicit coding for reading a FileDetails object
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
fileName = stream.readUTF(); // file name
fileSize = stream.readLong(); // file size
// file data as a series of byte[], length CHUNK_LEN
long toRead = fileSize;
// write file data to a File object, same path name
file = new File( fileName );
OutputStream os = new FileOutputStream( file );
while( toRead > 0 ){
// last byte arrays may be shorter than CHUNK_LEN
int chunkLen = toRead > CHUNK_LEN ? CHUNK_LEN : (int)toRead;
byte[] bytes = new byte[chunkLen];
int nread = stream.read( bytes );
// write data to file
os.write( bytes, 0, nread );
toRead -= nread;
}
os.close();
}
// explicit coding for writing a FileDetails object
private void writeObject(ObjectOutputStream stream)
throws IOException {
stream.writeUTF( fileName ); // file name as an "UTF string"
stream.writeLong( fileSize ); // file size
// file data as a series of byte[], length CHUNK_LEN
long toWrite = fileSize;
// read file data from the File object passed to the constructor
InputStream is = new FileInputStream( file );
while( toWrite > 0 ){
// last byte[] may be shorter than CHUNK_LEN
int chunkLen = toWrite > CHUNK_LEN ? CHUNK_LEN : (int)toWrite;
byte[] bytes = new byte[chunkLen];
int nread = is.read( bytes );
stream.write( bytes );
toWrite -= nread;
}
is.close();
}
private void readObjectNoData()
throws ObjectStreamException {
}
}
I've tested this with a short file:
File file = new File( "test.dat" );
FileDetails fd = new FileDetails( file );
FileOutputStream fos = new FileOutputStream("oos.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject( fd );
oos.close();
// test on a local system: rename test.dat to avoid overwriting
file.renameTo( new File( "test.dat.sav" ) );
FileInputStream fis = new FileInputStream("oos.dat");
ObjectInputStream ois = new ObjectInputStream(fis);
FileDetails fd1 = (FileDetails)ois.readObject();
ois.close();
// now the file test.dat has been rewritten under the same path,
// i.e., test.dat exists again and test.dat.sav == test.dat
I'm not sure whether the receiver will be happy with some file being written according to a path name being sent in the message.

How to read file with cyrillic path

Actually I have next code:
String f = LauncherFrame.class.getProtectionDomain().getCodeSource().getLocation().getPath(); // path to launcher
java.lang.System.out.println(f);
String launcherHash = "";
try{
MessageDigest md5 = MessageDigest.getInstance("MD5");
launcherHash = calculateHash(md5, f);
}catch (Exception e) {
java.lang.System.out.println(e){
return;
}
calculateHash function:
public static String calculateHash(MessageDigest algorithm,String fileName) throws Exception{
FileInputStream fis = new FileInputStream(fileName);
BufferedInputStream bis = new BufferedInputStream(fis);
DigestInputStream dis = new DigestInputStream(bis, algorithm);
while (dis.read() != -1);
byte[] hash = algorithm.digest();
return byteArray2Hex(hash);
}
It's work good on unix/windows when my .jar file haven't cyrillic characters in path. But when it have, I getting next exception:
java.io.FileNotFoundException:
C:\Users\%d0%90%d1%80%d1%82%d1%83%d1%80\Documents\NetBeansProjects\artcraft-client\build\classes (Can't find file)
How I can fix it?
This is from memory so the syntax may be a bit off, but the best is probably to use the built in URL support for opening streams directly from an URL;
URL url = LauncherFrame.class.getProtectionDomain().getCodeSource().getLocation();
then pass the URL to calculateHash instead of the filename and use URL's openStream method to get a stream with the content;
InputStream is = url.openStream();
BufferedInputStream bis = new BufferedInputStream(is);
...

Categories

Resources