Create a binary file in java - java

These are the related questions that might cause my question to be closed, even though I specify another question:
Java: How to write binary files? -> Doesn't really cover the point that I am talking about
create a binary file -> Absolutely doesn't cover the point
Editing a binary file in java -> They are talking about offsets and stuff, when I just need to write the data and stop
Binary files in java -> Vague.
And now to the point. I've got a file with a specific extension, to be more exact it's .nbs. I want to create a file and then write the specific data to it.
That might have sounded vague so let me show you the code I have started with.
try {
File bpdn = new File(getDataFolder() + "song.nbs");
if (!bpdn.exists()) {
bpdn.createNewFile();
}
FileOutputStream fos = new FileOutputStream(bpdn);
} catch (IOException e) {
e.printStackTrace();
}
I'll provide you even more details. So I've got a song.nbs file that I have created in the past, for myself. And now, whenever a person runs my application, I want it so there's a new song.nbs file with the exact contents of a file that I have on my PC right now. Therefore, I need to somehow get the bytes of my existing song.nbs and then copy and paste them in my Java application... or is it the way? I neither know how to get the bytes of my own file right now, nor do I know how to write them.

You need to create a resources folder. More info here.
Assuming your project structure is
ProjectName/src/main/java/Main.java
you can create a resources folder inside main/:
ProjectName/src/main/java/Main.java
ProjectName/src/main/resources/
Move your song.nbs you want to read inside resources/:
ProjectName/src/main/java/Main.java
ProjectName/src/main/resources/song.nbs
Now, get the InputStream of song.nbs stored there:
final ClassLoader classloader = Thread.currentThread().getContextClassLoader();
final InputStream is = classloader.getResourceAsStream("song.nbs");
Then, write this input stream to your new file:
final File bpdn = new File(getDataFolder() + "song.nbs");
if (!bpdn.exists()) bpdn.createNewFile();
final FileOutputStream os = new FileOutputStream(bpdn);
byte[] buffer = new byte[1024];
int read;
while ((read = is.read(buffer)) != -1) {
os.write(buffer, 0, read);
}

I think I came up with a solution, but I am not sure if this is works. I'd appreciate if you would take a look.
try {
File bpdn = new File(getDataFolder() + "badpiggiesdrip.nbs");
if (!bpdn.exists()) {
bpdn.createNewFile();
}
FileOutputStream fos = new FileOutputStream(bpdn);
fos.write(new byte[] {
Byte.parseByte(Arrays.toString(Base64.getDecoder().decode(Common.myString)))
});
} catch (IOException e) {
e.printStackTrace();
}
Common.myString is just a string, that contains data of this type:
(byte) 0x21, (byte) 0x5a, .....
and it's encoded in Base64.

Related

Cant extract single files from Tar, 0kb size, Java

I have been created a application which shall extract single files from tar-archive. The application reads the *.tar properly, but when i try to extract files, the application just create new files with correct filename... The files is empty (0kb). So... I probably just create new files instead of extract...
I'm a totally beginner at this point...
for(TarArchiveEntry tae : tarEntries){
System.out.println(tarEntries.size());
try {
fOutput = new FileOutputStream(new File(tae.getFile(), tae.getName()));
byte[] buf = new byte[(int) tae.getSize()];
int len;
while ((len = tarFile.read(buf)) > 0) {
fOutput.write(buf, 0, len);
}
fOutput.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Assuming tarFile is a TarArchiveInputStream you can only read an entry's content right after calling tarFile.getNextTarEntry().
The stream is processed sequentially, so when you invoke getNextTarEntry you skip over the content of the current entry right to the next entry. It looks as if you had read the whole archive in order to fill tarEntries in which case you've already read past the last entry and the stream is exhausted.

Saving files received through DatagramPackets in Java

I am trying to send Files in fragments using DatagramPackets in Java (part of an assignemt.) When I am trying to save the incoming File I get access denied error, but I believe that it is not a permissions issue.
Here is the brunt of it:
I let the user sending the file to choose it using FileChooser. And create a new Message object.
//....
File f = content.showFileChooser();
byte type = Byte.parseByte("4");
Message m;
try {
if (mode == 1){
m = new Message(f, content.getServerData().getFragmentSize(), (short) (sentMessages.size()+1), type);
serverThread.send(m);
}
//...
During Message creation the file gets split up into byte arrays, where the size of each array is predetermined by the user. The code is quite lengthy so I am not going to post the chopping process, but this is how I convert the File object into a big byte[] which then gets chopped up
Path p = Paths.get(file.getAbsolutePath());
this.rawData = Files.readAllBytes(p);
After the Message is created and chopped up into byte arrays I send them using DatagramPackets. The other side then uses those to create a new Message object. Once all fragments arrive rawData is extracted from the Message object again. The problem believe lies here:
Message m = receivedMessages.get(msgIndex-1);
byte[] fileData = m.getFile();
if (fileData != null){
System.out.println("All file fragments received.");
content.append("Received a file in" + m.getFragmentCount()+" fragments. Choose directory. " ,1);
//I BELIEVE THIS TO BE THE CRITICAL POINT
String filePath = content.chooseDirectory();
if (filePath == null)
return;
FileOutputStream fos;
try {
fos = new FileOutputStream(filePath);
fos.write(fileData);
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Once all fragments arrive I let the user select a directory using FileChooser with DIRECTORY_ONLY choice mode. As I understand, FileOutputStream requires a full path for the new File. Do I have to send the file name and extension separately or can it be extracted from the received File data?
You are writing directory path to filePath, then try to open that directory with FileOutputStream. No wonder that doesn't work, you have to specify the filename too.
String filename = "myfile.txt"; //Or receive and set this some other way
File outFile = new File(filePath, filename);
fos = new FileOutputStream(outFile);
I don't see you sending/receiving the filename anywhere, though. You'll need to either make it constant or transfer it along with file contents.

Writing multiple files to one file (like a file system)

I'm trying to store multiple data files that I have created into one file. Each file has an ID# (0-35) and each holds some data. But what I want is to be able to store all the files in one file called 'data.xx', then be able to access the each of the files data inside the data.xx file.
public static void pack(int id) {
try {
RandomAccessFile raf = new RandomAccessFile("./data/data.xx", "rw");
ByteArrayInputStream bis = null;
try {
byte[] data = toByteArray(id);
bis = new ByteArrayInputStream(data);
raf.seek(raf.length());
System.out.println(raf.length());
while (bis.read(data, 0, data.length) >= 0) {
raf.write(data, 0, data.length);
}
} finally {
bis.close();
raf.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
toByteArray(id) calls the separate data files then puts it into byte array. All the files seem to write fine to the data.xx file. The problem I'm having is I'm not really sure how to read the data.xx file so I can get the data from the files that are stored in it. I hope this makes sense. Also I don't need any compression and I don't want to use a library for this.
Thank you
The simplest way is use markup:
<id_0> content of file 0 </id_0>
...
<id_35> content of file 35 </id_35>
You write file like that and read content inside tags with substring
I would prepend the output file with the offsets of the start of each contained file. A special "token" is a nice idea, but files can contain any byte or bytes; making the idea not realistic. That way your "index" will terminate with something you can't confuse with file data because the information occurres before you expect arbitrary data ... say, 0? Please comment if I misunderstood this question.

Java : download file outside server context

I need to save a file and download file in directory outside server context.
I am using Apache Tomacat
I am able to do this in directory present in webapps directory of application
If my directory structure is as follows,
--src
--WebContent
-- uploaddir
-- myfile.txt
Then I am able to download in by simply.
download
But, problem is when file is in some other directory say d:\\uploadedfile\\myfile.txt
then I wont be able to download it, as resource is not in server context as above.
I have file path to uuid mapping,
like,
d:\\uploadedfiles\\myfile.txt <-> some_uuid
then I want file should be downloaded, on click of following,
download
So, How to make file downloadable when it is outside the server context,
I heard about getResourceAsStream() method which would do this , But would any one help me on how to do this, probably with simple code snippet?
Try the below code which you can write in filedownloadservet. Fetch the file name from the request parameter and then read and write the file.
If you need to do some security checks then do that before processing the request.
File file = new File("/home/files", "file name which user wants to download");
response.setContentType(getServletContext().getMimeType(file.getName()));
response.setContentLength(file.length());
BufferedInputStream inputStream = null;
BufferedOutputStream outputStream = null;
try {
inputStream = new BufferedInputStream(new FileInputStream(file));
outputStream = new BufferedOutputStream(response.getOutputStream());
byte[] buf = new byte[2048];
int len;
while ((len = inputStream.read(buf)) > 0) {
outputStream.write(buf, 0, len);
}
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
//log it
}
}
// do the same for input stream also
}
here i found the answer,
response.setContentType("application/msword");
response.setHeader("Content-Disposition","attachment;filename=downloadname.doc");
File file=new File("d:\\test.doc");
InputStream is=new FileInputStream(file);
int read=0;
byte[] bytes = new byte[BYTES_DOWNLOAD];
OutputStream os = response.getOutputStream();
while((read = is.read(bytes))!= -1){
os.write(bytes, 0, read);
}
os.flush();
os.close();
Base path will not work that is for HTML and it works if the base path is also exposed by your web server which does not look like case here.
To download an arbitary file you need to open the file using a FileInputStream (and surround it by a buffered input stream), read a byte, then send that byte from your servlet to the client.
Then there are security concerns, so should google that (basically not give access to any file but only file that is to be shared, audit download etc as needed.
Again in your servlet set the mime type etc and then open a input stream and write the bytes to the output stream to client

could not delete file neither via java nor manually

I have the following situation, within a servlet a create a file and then have to delete it.
When executing the file, I figured out that the file is still in the server, so I tried to remove it manually, I can't, I get the following message :
this file is opened by another program : javaw.exe
Here is my code :
public class GenerateFile extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws IOException {
System.out.println("ok");
String fileName = request.getParameter("fileName");
Integer nbrParam = Integer.parseInt(request.getParameter("nbrParam"));
String[] valueParam = new String[nbrParam+1];
for(int i =1;i<=nbrParam;i++)
{ System.out.println(request.getParameter("param"+i));
valueParam[i]=request.getParameter("param"+i);
}
FileInputStream in = new FileInputStream("C:\\Users\\free\\Desktop\\myworkspace\\gestionRH\\WebRoot\\fiches\\"+fileName+".doc");
POIFSFileSystem fs = new POIFSFileSystem(in);
HWPFDocument doc = new HWPFDocument(fs);
Range r = doc.getRange();
for(int i=1;i<=nbrParam;i++)
{ System.out.println("<param"+i+">");
System.out.println(valueParam[i]);
r.replaceText("<param"+i+">", valueParam[i]);
}
File file = new File("C:\\Users\\free\\Desktop\\myworkspace\\gestionRH\\WebRoot\\fiches\\temp");
File temp = File.createTempFile("monfile",".doc",file);
String tempName =temp.getName();
doc.write( new FileOutputStream(temp));
OutputStream out = response.getOutputStream();
response.setContentType("application/rtf");
response.setHeader("Content-Disposition","attachment; filename=Decision");
FileInputStream in1 = new FileInputStream(temp);
byte[] buffer = new byte[4096];
int length;
while ((length = in1.read(buffer)) > 0){
out.write(buffer, 0, length);
}
in1.close();
out.flush();
System.out.println("C:\\Users\\free\\Desktop\\myworkspace\\gestionRH\\WebRoot\\fiches\\temp\\"+tempName);
File f = new File("C:\\Users\\free\\Desktop\\myworkspace\\gestionRH\\WebRoot\\fiches\\temp\\"+tempName);
f.delete();
return null;
}
}
You should close all the file-reading object instances. Besides, if you can delete the file manually, you should close java and then delete it, javaw is the process that launches java outside the console.
The problem is you are creating a new FileOutputStream(tempName) to write on that file, but never closing that outputstream (or another outputstream linked to it).
Do this:
FileOutputStream fos = newFileOutputStream(tempName);
// use it
fos.close(); // CLOSE IT!!
// then you can delete the file
Simplify
Maybe you could do the work another way, without temp files...
by example: doc.write(new FileOutputStream(tempName)) could be replaced by:
doc.write(response.getOutputStream());
This way doc sends its bytes directly to where you need them, not to a temp file eliminating the need for it.
The idea behind input/output streams is composing them. Input/OutputStream are the abstract base classes. And there are a lot of implementations:
based on memory: ByteArrayInput/OutputStream
based on files: FileInputOutputStream
compressing/decompressing to another outputstream: GZipInputOutputStream
and so on
The beauty of it is applying decorator pattern to add functionality. By example:
new GZipOutputStream(new ByteArrayOutputStream());
// creates an outputstreams that compress data received and send it to the other stream
// the BAOS then writes the received bytes to memory
new GZipOutputStream(new FileOutputStream());
// it's the same but sending compressed bytes to a file.
Seems like, you are not closing the file(out), thus it remains with the thread of this action, which is restricting it to get deleted.
Hope it helps.
maybe you should try ProcMon to find out what process exactly holds the file opened
For IO features, I would to suggest to use some kind of jar already provided by community.
For example, common-io.x-x.jar, spring-core.jar
Eg, org.apache.commons.io.FileUtils;
FileUtils.copyDirectory(from, to);
FileUtils.deleteDirectory(childDir);
FileUtils.forceDelete(springConfigDir);
FileUtils.writeByteArrayToFile(file, data);
org.springframework.util.FileSystemUtils;
FileSystemUtils.copyRecursively(from, to);
FileSystemUtils.deleteRecursively(dir);
good luck!
Whenever you open a file handler, you should close it. In a Java application that you want to run for a long period of time, you are strongly recommended to close all unused file handlers soon after you finish working with them.
Examples of common file handlers are FileOutputStream and FileInputstream. Here is a good example of how you open and close the FileOutputStream
FileOutputStream fos = null;
try {
fos = new FileOutputStream(tempName);
// do something
} catch (IOException ex) {
// deal with exceptions
} finally {
// close if fos is not null
if (fos != null) {
fos.close();
}
}
You should never do this:
doc.write( new FileOutputStream(temp));
because you can never close the file handler if it has no refernce to it.

Categories