Is there a class to hold a file (content and name) - java

I only want to be sure before creating it. Is there a class to "store" a file in java. In my case, I only need name and content (byte array?!).
Using Lombok it is as simple as this:
import lombok.Value;
#Value
public class Document {
private String fileName;
private byte[] content;
}
But I would prefer to use a "native" class if there is one.

Your own class is fine.
public class Document {
private String fileName;
private byte[] content;
public Document(String fileName) {
this.fileName = fileName;
this.content = Files.readAllBytes(Paths.get(fileName));
}
}
Usage:
Document d = new Document("/path/to/file");
You should definitely consider whether you actually need the file name later on in the code or not, as it may be enough for you to use the content without a wrapping class.
Also note Java's IO provides many different ways to get the contents of a file - you are not limited to byte arrays. See Files for a non-exhaustive list of file-related operations, including the Files.lines() method to get a Stream<String> of all lines in a (text) file.

Related

how do i marshal data for TCP streaming?

So for a homework assignment, I have a example of how to marshal data and unmarshal.
The structure they gave us was this:
Event is an interface.
Wireformat is a class that "inherits" an Event.
WireFormatWidget is a class with the actual code that has the marshal and unmarshal.
I have separate threads that handle the sending data in byte array using TCP.
What I have an issue is that when I create a Wireformat object. I run into issue with a thread trying to marshal the data.
Exception in thread "main" java.lang.NullPointerException
at myhw.WriteFormatWidget.getBytes(WriteFormatWidget.java:38)
The interface structure defines the data as a message, a type of message as an integer, a timestamp (of what I am assuming is Date and getTime of that date), and a tracker. I am not sure what the tracker is.
I am told this structure is the best method to sending data which is why I am trying to implement this code style.
The WriteFormatWidget consist of this:
private int type;
private long timestamp;
private String identifier;
private int tracker;
So for my wireformat, I created it as a class that extends WireFormatWidget and implements Event because that was the only way Eclipse did not spit an error or suggest changing WireFormatWidget or Event.
Now when I hardcode my specific wireformat, I instantiate it and it seems to not be able to call getBytes() with the hardcoded values I uses for the same variables.
public class MyWireFormat extends WireFormatWidget implements Event {
private String identifier = "here is my custom wireformat";
....
When I print out the identifier in the getBytes in WireFormatWidget, I get null and not the expected identifier I hardcoded. So I must not be "inheriting" appropriately. What am I doing wrong?
EDIT: WireFormatWidget (given)
public class WriteFormatWidget {
private int type;
private long timestamp;
private String identifier;
private int tracker;
public byte[] getBytes() throws IOException {
byte[] marshalledBytes = null;
ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(baOutputStream));
dout.writeInt(type);
dout.writeLong(timestamp);
System.out.println("getBytes using identifier: " + identifier);
byte[] identifierBytes = identifier.getBytes();
int elementLength = identifierBytes.length;
dout.writeInt(elementLength);
dout.write(identifierBytes);
dout.writeInt(tracker);
dout.flush();
marshalledBytes = baOutputStream.toByteArray();
baOutputStream.close();
dout.close();
return marshalledBytes;
}
}
I'll save space by not posting the unmarshalling portion. But its the same thing just in reverse.
The issue I am having is printing the data from the Client-side as proof of what I am sending beforehand.
So I will perform a simple test like print the type or print the identifier. It fails and I have null.
You're not initializing WireFormatWidget#identifier. It's declared but never initialized. Add a constructor to WireFormatWidget and provide a String as the identifier.
You need to implement something that implements Serializable, or implement directly Serializable (I think is simpler).
You do not specify many things about your interface event, but probably will inherit from Serializable, at least if you are going to implement standard java serialization.
If Event implements Serializable so it is ok, otherwise if you use another serialization method you need to specify more about it.
Assuming that you implement Serializable you need to create a ByteBuffer and call to writeObject. To create the stream you can check for example Java Serializable Object to Byte Array, so joining all:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream stream = new ObjectOutputStream(bos);
stream.writeObject(yourinstancetoserialize);
out.flush();
byte[] yourBytes = bos.toByteArray();
...
Probably you will need to implement the writeObject directly. In that case you use the ObjectOutputStream methods to serialize the properties, check them in https://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html for example.
private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
stream.writeInt(this.type);
stream.writeLong(this.timestamp);
stream.writeBytes(this.identifier); or stream.writeChars(this.identifier);
stream.writeInt(this.tracker);
...
}

AspectJ / Generate methods using compile-time reflection

I just heard of AspectJ and it doesn't look too easy to understand, so I want to know beforehand if it (or anything else) will help me with my problem or not.
I have bunch of simple POJO classes and want to write binary serializers for them but without writing Write/Read methods by hand for each class. I could've done so with help of reflection but that will affect runtime performance. I believe I need something similar to Macroses in Scala with compile-time reflection and quasiquotes.
Update:
I'm unable to use any serialization available, because I have custom binary protocol which I can't modify (online game)
Update 2:
Example POJO with it's read, write and some helper methods. Not final version, there possibly could be some annotations, for example, but general structure should be the same. I also omitted inheritance for simplicity, in reality LoginPacket extends CommandPacket class which in turn extends Packet class.
public class LoginPacket {
public short length;
public int sessionId;
public short command;
public short error;
public String reason;
private String getString(ByteBuffer data) {
short length = data.getShort();
byte[] stringData = new byte[length];
data.get(stringData);
return new String(stringData, "UTF-8");
}
private void putString(ByteBuffer data, String someString) {
data.putShort(someString.length());
byte[] stringData = someString.getBytes("UTF-8");
data.put(stringData);
}
public static LoginPacket read(ByteBuffer data) {
LoginPacker loginPacket = new LoginPacket();
loginPacket.length = data.getShort();
loginPacket.sessionId = data.getInt();
loginPacket.command = data.getShort();
loginPacket.error = data.getShort();
loginPacket.reason = getString(data);
return loginPacket;
}
public void write(ByteBuffer data) {
data.putShort(this.length);
data.putInt(this.sessionId);
data.putShort(this.command);
data.putShort(this.error);
putString(data, this.reason);
}
}
I don't think you need to use AspectJ to modify your classes. I don't see what benefits using compile team weaving would add. I would suggest having your POJOs use implements Serializableand then serialize your objects using an ObjectOutputStream.
A simple example writing an object to a file:
outputStream = new ObjectOutputStream(new FileOutputStream(filePath));
outputStream.writeObject(yourObject);
...
// do whatever else and close stream
Similar questions:
Saving to binary/serialization java
Best way to store data for your game? (Images, maps, and such)

Should i store file names in Java Enum or properties file

I want to store file names, which keep on changing as the new files get added. I am looking for a minimum change in server code later when there is a need to support a new 'file' The thought I have is to store them either in properties file or as Java enum, but still thinking which is a better approach.
I am using REST and having 'file type' in the URL.
Example rest url:
hostname/file-content/TYPE
where value of TYPE could be any of these: standardFileNames1,standardFileNames2,randomFileName1,randomFileName2
I have used TYPE to group the files, so as to minimize the change in url when a new file is added. Dont want to have file names in the URL due to security issues.
my thought goes like this:
having as ENUM:
public enum FileType
{
standardFileNames1("Afile_en", "Afile_jp"),
standardFileNames2("Bfile_en","Bfile_jp"),
randomFileName1("xyz"),
randomFileName2("abc"),
...
...
}
having as properties file:
standardFileNames1=Afile_en,Afile_jp
standardFileNames2=Bfile_en,Bfile_jp
randomFileName1=xyz
randomFileName2=abc
I know having this in properties will save build efforts on every change, but still want to know your views to figure out best solution with all considerations.
Thanks!
Akhilesh
I often use property file + enum combination. Here is an example:
public enum Constants {
PROP1,
PROP2;
private static final String PATH = "/constants.properties";
private static final Logger logger = LoggerFactory.getLogger(Constants.class);
private static Properties properties;
private String value;
private void init() {
if (properties == null) {
properties = new Properties();
try {
properties.load(Constants.class.getResourceAsStream(PATH));
}
catch (Exception e) {
logger.error("Unable to load " + PATH + " file from classpath.", e);
System.exit(1);
}
}
value = (String) properties.get(this.toString());
}
public String getValue() {
if (value == null) {
init();
}
return value;
}
}
Now you also need a property file (I ofter place it in src, so it is packaged into JAR), with properties just as you used in enum. For example:
constants.properties:
#This is property file...
PROP1=some text
PROP2=some other text
Now I very often use static import in classes where I want to use my constants:
import static com.some.package.Constants.*;
And an example usage
System.out.println(PROP1);
Source:http://stackoverflow.com/questions/4908973/java-property-file-as-enum
My suggestion is to keep in properties or config file and write a generic code to get the file list and parse in java. So that whenever a new file comes, there will be no change on server side rather you will add an entry to the properties or config file.

File Output between multiple runtimes?

I am working on this project where the user enters some data which is written to an XML file.This part is working fine.
Now when the user runs the program he should be able to append to that file. Instead it creates a new file with just one entry!
A fileoutput stream is also not the solution.
Here is the code for serializing to XML
String medicine=medicfield.getText();
String doctor=dnamefield.getText();
int duration=Integer.parseInt(dodfield.getText());
int amount=Integer.parseInt(cyclefield.getText());
int inter=Integer.parseInt(intval.getText());
PrescripManager pm=new PrescripManager();
pm.setDcycle(amount);
pm.setDosage(duration);
pm.setInterval(inter);
pm.setmedName(medicine);
pm.setdocName(doctor);
try{
FileOutputStream file = new FileOutputStream("file.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(PrescripManager.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
// output pretty printed
jaxbMarshaller.marshal(pm, file);
}
catch(Exception ex)
{
erlbl.setText(ex.getMessage());
}
And the Class::
#XmlRootElement
public class PrescripManager {
private String medname,docname;
private int interval,dcycle,dosage;
private Date dt;
public String getmedName() {
return medname;
}
public void setmedName(String medname) {
this.medname = medname;
}
public String getdocName() {
return docname;
}
public void setdocName(String docname) {
this.docname = docname;
}
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
}
public int getDcycle() {
return dcycle;
}
public void setDcycle(int dcycle) {
this.dcycle = dcycle;
}
public int getDosage() {
return dosage;
}
public void setDosage(int dosage) {
this.dosage = dosage;
}
}
First of all, you are writing an XML file. You can not just append to an XML file, because that would mean you are writing after then closing top level tag, resulting in invalid XML file.
You have at least three choices:
read old file in, add to the actual data, then write entire XML-file back.
write multiple files, each a valid XML file, with sequence number or timestamp in file name.
do not use XML, use a format which can be appended to
As a side note, if you want to append to file, you can open it in append mode. That will make every write to it append (at least on Unix, when file is opened in append mode, and I presume it works the same in Windows).
How to open file in append mode in Java: http://docs.oracle.com/javase/6/docs/api/java/io/FileOutputStream.html#FileOutputStream(java.io.File, boolean)
You can use the "FileWriter" class which allows you to write at the end of a file. See
http://docs.oracle.com/javase/6/docs/api/java/io/FileWriter.html
This link should help you:
http://www.coderanch.com/t/276346//java/do-open-file-append-mode
I think it should work if you use
FilterWriter file = new FileWriter( "file.xml" , true );
instead of
FileOutputStream file = new FileOutputStream("file.xml");
You are using JAXB to process XML files, so it's better that you change your XML file format and Java class to support this.
You can add a new class as collections of PrescripManager class instances. Something like PrescripManagerList.
public class PrescripManagerList{
#XmlElementWrapper(name = "prescripManagers")
#XmlElement(name = "prescripManager")
private ArrayList<PrescripManager> prescripManagers;
}
When you running your code, try to read an existing XML file using JAXB unmarshaller to get a PrescripManagerList object, then add a new PrescripManager object to the ArrayList, then write the updated PrescripManagerList object to file using JAXB marshaller.

Memory management for a object that has a file.

I was wondering if someone could explain the best solution for the smallest memory footprint for an object that has a file in the following situation...
There could be 1 to a few hundred Foo classes.
Thread safety will be important down the road.
Not every Foo class's file is accessed every time.
Each file is unique.
The file in a Foo class may be accessed more than once.
I was planning to profile the solutions below to find the lowest memory footprint and i have a good idea which one would work best but I was interested in some feedback. Solution 1 seems like the best approach but it feels prone to memory leaks the more something accesses the getter. Thoughts?
Solution 1:
public class Foo{
private final String pathToFile;
public class Foo(String pathToFile){
this.pathToFile = pathToFile;
}
public File getFile(){
return new File(pathToFile);
}
}
Solution 2:
public class Foo{
private final File file;
public class Foo(String pathToFile){
this.file = new File(pathToFile);
}
public File getFile(){
return file;
}
}
Solution 3:
public class Foo{
private final String pathToFile;
private File file = null;
public class Foo(String pathToFile){
this.pathToFile = pathToFile;
}
public File getFile(){
if (file == null){
file = new File(pathToFile);
}
return file;
}
}
It all depens on what you want to do with the program, If you need the path in other places then you should have a reference to that. if you need the file, again you would need a reference. Another solution you could do is in the second solution have a method that will return the path: file.getPath();
So overall either the first solution (if you need the path at some point),
or solution 2 if you do not.
It really shouldn't make a big deal either way. The first option will create a new file reference every time that its called, so if you call this 100,000 times AND keep the reference to the files, then it might make an impact. Otherwise, it just depends on if it makes sense to have a reference to the Foo objects file, or if Foo is more of a service than an object and its goal is to return any reasonable reference to the file.

Categories