Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 7 years ago.
Improve this question
I hope the question is suitable for here. I've designed an application layer protocol, say similar to HTTP. How can I define, and set the header fields in Java? Overall, I just want to write a simple client-server program that transfers "Hello World" string, but using my own protocol.
Assume header fields are similar to the following. So the "Hello World!" data comes after this header.
When you write to a socket, you're writing an stream of bytes. It's common, as in the table you included in your question, to start that stream with a standard series of bytes that gives the information needed to make sense of the remaining stream.
For example, of you simply want to send a string the minimum you'd need to add would be the string length like this:
|message length|data|
Which could be written like this:
String data = "Hello, world!";
ByteBuffer buffer = ByteBuffer.allocate(data.length + Integer.BYTES);
buffer.putInt(data.length);
buffer.put(data.getBytes("UTF-8"));
buffer.flip();
channel.write(buffer);
Adding in additional header information is no different, you just need to define a format for it in the stream.
You might for example use a format like this
|message length|header count|header size|header type|header data|data|
Which could be written like this:
Map<Integer, String> headers = ...
String data = "Hello, world - look at my headers!";
int headerBuffersLength = 0;
List<ByteBuffer> headerBuffers = new ArrayList<>();
for(Integer headerType : headers.keySet())
{
String headerData = headers.get(headerType);
ByteBuffer headerBuffer = ByteBuffer.allocation(headerData.size + Integer.BYTES + Integer.BYTES);
headerBuffer.putInt(headerData.length);
headerBuffer.putInt(headerType);
headerBuffer.put(headerData.getBytes("UTF-8"));
headerBuffer.flip();
headerBuffers.add(headerBuffer);
headerBuffersLength += headerBuffer.limit();
}
ByteBuffer buffer = ByteBuffer.allocate(data.length + headerBuffersLength + Integer.BYTES + Integer.BYTES);
buffer.putInt(data.length + headerBuffersLength);
buffer.putInt(headerBuffers.size());
for (ByteBuffer headerBuffer : headerBuffers)
{
buffer.put(headerBuffer);
}
buffer.put(data.getBytes("UTF-8"));
buffer.flip();
channel.write(buffer);
That's the basics, the code is very simple to write, but you might want to look at Google Protocol Buffers if you're doing anything more complicated.
There are many ways. It is quite common that this kind of specification comes with an xsd. If that is the case, you can use JAXB2 to parse it and create a set of Java Classes.
If that is not the case, may be you have the specification in such way you can do text processing and extract attributes and types to automate Java Class construction, using grep, sed, and so on.
If finally you have to build the Java Classes on your own, I will do something like following:
package my.package.ams;
public class ASMHeader {
private Integer version = null;
private Integer msgType = null;
private Integer priority = null;
...
public String getVersionString (){
return String.format("%02d", (version != null)?version:0);
}
public Integer getVersion(){
return version;
}
public void setVersion(Integer version){
if(version >= 0 and version < 100){
this.version = version;
}
}
public Integer getMsgType(){
return msgType;
}
public void setMsgType(Integer MsgType){
if(msgType >= 0 and msgType < 5){
this.msgType = msgType;
}
}
//And so on
....
}
Finally processing rules are not shown in yournpic, but you will have to understand and implements.
Take into account the possibility to thrown exception where version, msgType and other variables, doesn't meet the rules expressed in the document.
Hope it helps!
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 6 years ago.
Improve this question
Ive just started learning Java and I spent most of the day watching video tutorials, however now I've decided to do something practical, as I dont think I can absorb anymore information today.
I had an idea to develop a fitness app a while ago, but was hit by how difficult that actually is without any knowledge, so I thought I will start by just creating a macro counter. I created a class:
public class Food {
private String name;
public int weight;
private int calories;
private int protein;
private int fat;
private int carbs;
public int tCals = weight * calories;
public int tProtein = weight * protein;
public int tFat = weight * fat;
public int tCarbs = weight * carbs;
public void macrocounter(){
System.out.println("Total calories: " + tCals);
System.out.println("\nProtein: " + tProtein);
System.out.println("\nCarbs: " + tCarbs);
System.out.println("\nFat: " + tFat);
System.out.println("-------------");
}
}
Now what I am having problems with is creating a database. I want to add at least 10 simple meals to begin with, they would all have the macros set in stone, the user would just type in the name of the meal and how many grams he ate, then the app would recognize the food from the database, fill in weight, and print out the total macros.
I am not asking here how to write the specific code, just can you point me to what I should read up on more to be able to do this? Java is an insanely vast language, and I am having trouble to find the actual information I need on creating a database.
Thank you.
Some oneline tutorials are good. But I would consider investing in a good Java book. I found BigJava Cay S. Horstmann a really helpful source of information. It gives you plenty of exercises and opportunity to practice code, and explains things in a very clear way. I would only go to online tutorials if I had trouble following a certain methodology in a book. But I wouldnt use them as a learning resource, as they may not be correct.
It is an expensive book though but you might be able to get an older edition for cheeap or a second hand copy. Oracle's website also has useful written tutorials for you to follow https://docs.oracle.com/javase/tutorial/ But I found the book easier to follow.
You want just to store the data in main memory? or in a real database to disk?
If it is the first option, you can do this:
ArrayList<Food> foods = new ArrayList<Food>();
Once you have your list, you can add things like this:
Food f = new Food(...data...); //You need a constructor
//to pass the data.
foods.add(f);
To consult it you can do a number of things:
Food f0 = foods.get(0);
Food f1 = foods.get(1);
You can also query for a particular object:
if (foods.contains(f0) {
// ...
}
Google for "java class ArrayList" and you'll see what you can do.
If, on the contrary, you want to create a real database, you need to read about JDBC drivers. To begin, I recommend you sqlite.
package consultarcalibredb;
import java.sql.*;
public class ConsultarCalibreDB {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Connection conn = null;
int id;
String title, author, path;
try {
DriverManager.registerDriver(new org.sqlite.JDBC());
conn = DriverManager.getConnection("jdbc:sqlite:/home/user/folder/file.db");
String sql = "select id, title, author_sort, path from books where author_sort like '%orwell%'";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
System.out.println("id\ttitulo\tautor\tpath");
while (rs.next()) {
id = rs.getInt("id");
title = rs.getString("title");
author = rs.getString("author_sort");
path = rs.getString("path");
System.out.println(id+"\n"+title+
"\n"+author+"\n"+path);
System.out.println();
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
Thank you for your help, I got a lot of suggestions on what I should learn and from where. I dont know how to close the question, but if you do, please do so.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Consider the following siutation. A user can enter something like
30D, 90D, 180D, 360D, 1M, 3M, 6M, 12M, 1Y
(D=day, M=month, Y=year).
I want to compute the number of months with the following two methods.
private int getLengthOfPeriodInMonths(Integer lengthOfPeriod, String unitOfPeriod) {
int periodInMonths = lengthOfPeriod;
if ("D".equals(unitOfPeriod)) {
periodInMonths = lengthOfPeriod / 30;
} else if ("Y".equals(unitOfPeriod)) {
periodInMonths = lengthOfPeriod * 12;
}
return periodInMonths;
}
private int getLengthOfPeriodInMonths(Integer lengthOfPeriod, String unitOfPeriod) {
if ("D".equals(unitOfPeriod)) {
lengthOfPeriod = lengthOfPeriod / 30;
} else if ("Y".equals(unitOfPeriod)) {
lengthOfPeriod = lengthOfPeriod * 12;
}
return lengthOfPeriod;
}
Because java works with call-by-value with a reference passed as a value lengthOfPeriod won't change outside of the method. I am not sure what is more appropriate to use.
I know that this method could be refactored by using an enum Periods or something like that. But let's not discuss this here.
Assigning to method parameters is not a good idea (and they should've been made final by default IMHO). If you really want to avoid the extra variable (not that it really makes a difference), you can put returns in your if clauses.
But don't use parameters as "automatic local variables". It can cause hard to see bugs and doesn't make your code any more performant.
The only difference is that you use an own variable int periodInMonths = lengthOfPeriod; in the first method. But this isn't necessary!
You can use the second one.. It does what it should!
int lengthOfPeriodInMonths = getLengthOfPeriodInMonths(lengthOfPeriod, unitOfPeriod);
and you have the calculated int outside of the method stored in lengthOfPeriodInMonths
P.S.: This call
lengthOfPeriod = lengthOfPeriod / 30;
is equivalent to
lengthOfPeriod = new Integer(lengthOfPeriod / 30);
(look "auto-boxing" in Java).
So, as you said, Java uses call-bay-value. The variable lengthOfPeriod gets assigned a new refernece in this call. So this calculation would be lost outside the method! That's why you must return the newly computed value!
First advice: never ever modify the method parameters. They should reflect the value passed by the user of the method at all times.
Second advice: if someone advises you to never do something, especially if he or she uses the phrase "never ever", take his or her advice with a grain of salt. There are no rules without exceptions (never ever ;-). Such rules are great rules of thumb, but always use your own judgement. Choose the solution which you think is clearer. I know of some situations where I found modifying method parameters was more readable than the alternative.
For example, sometimes you might want to allow the user of the method to pass null to the method, but then replace it with some default value. I find the following method
public void doSomething(String s) {
if (s == null) s = "";
System.out.println(s);
}
much clearer than introducing a local variable just to include the default value:
public void doSomething(final String s) {
String sOrEmpty = s == null ? "" : s;
System.out.println(sOrEmpty);
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I need to develop a parser for a binary message exchange format i.e., a message parser which parses a binary message into an java object representation. I would like to ask what useful patterns could be used to implement a parser in a most flexible way. Could anybody describe this in a nutshell or provide resources to read?
Since youre trying to read binary data and transform it into Java Object, there are many approaches, but first thing first, you must know the structure/protocol of your binary.
The pattern I show you bellow is the style that I (if I were you) will use for this scenario.
Make sure you have an input stream that will stream out your binary data. If what you have is a byte array, Make a ByteArrayInputStream.
In your objects graph, each node/object should implement something like parseIn(InputStream s) method.
public class Parent extends ArrayList<Child> {
int age;
// ... more code here
public void parseIn(InputStream is) throws IOException {
// .. logic to read the stream into this instance.
DataInputStream dis = new DataInputStream(is);
this.age = dis.readInt();
// .. if necessary
Child c = new Child();
c.parseIn(InputStream is);
this.add(c);
}
// ... more code here
}
public class Child {
int height;
short weight;
Date birthdate;
public void parseIn(InputStream is) throws IOException {
// .. logic to read the stream into this instance.
DataInputStream dis = new DataInputStream(is);
height = dis.readInt();
weight = dis.readShort();
birthdate = new Date(dis.readLong());
}
}
So, when you obtain your stream, you simply
InputStream stream = this.getInputStream();
Parent p = new Parent();
parent.parseIn(stream);
And so on and so forth.
Some times, you need to read the underlying stream for some hint you need to read forward. For example when reading a string data in the binary stream. Either you keep reading byte-by-byte until you find a terminator byte (as of C's style 0 termination character). Or to provide the string length on the first byte and then read a byte array of that length.
I hope you get the Idea. And I hope it helps.
I am working on DNA proteins alignment project "readseq" . Its "flybase " package contains java code having " charToByteConverter" class which does not compile and gives the " type deprecated " message. (http://iubio.bio.indiana.edu/soft/molbio/readseq/java/).
Here readseq source can be foundI need to add some more functionality into this application, don't know how to fix it to proceed towards my goal. I am a kind of new bie in java. Plz help if possible. Readseq is with its gui is easily available on net.
It just converts an array of given characters to bytes. Here is some info about it: (docjar.com/docs/api/sun/io/CharToByteConverter.html) . I don't know what to do about this being deprecated.
It is an abstract class used as under:
protected byte[] getBytes(CharToByteConverter ctb) {
ctb.reset();
int estLength = ctb.getMaxBytesPerChar() * count;
byte[] result = new byte[estLength];
int length;
try {
length = ctb.convert(value, offset, offset + count,
result, 0, estLength);
length += ctb.flush(result, ctb.nextByteIndex(), estLength);
} catch (CharConversionException e) {
length = ctb.nextByteIndex();
}
if (length < estLength) {
// A short format was used: Trim the byte array.
byte[] trimResult = new byte[length];
System.arraycopy(result, 0, trimResult, 0, length);
return trimResult;
}
else {
return result;
}
}
The javadoc comment says it all:
Deprecated! Replaced - by java.nio.charset
Look for a replacement class/method in the java.nio.charset package.
Note that using classes in the JDK that are not part of the officially documented API is a bad idea in the first place.
This is a perfect case for Adapt Parameter, from Michael Feathers book Working Effectively With Legacy Code.
Shameless self-plug: Here's a short prezi I did on it. It has a step-by-step breakdown of what you need to do.
Essentially, you're going to have to modify the code you have and apply the Adapter Pattern to the parameter. You'll want to define your own interface (let's call it ByteSource), make getBytes() take your interface instead (getBytes(ByteSource ctb)), then make the Adapter that internally has a CharToByteConverter for testing. To fix the broken library, you should make one that has a java.nio.charset instead.
I know that the audience of JIF is very small in numbers, but that's that Stack Overflow is for.
My question has to do with if anyone has a snipset with which I can declassify a String and send it as output to screen.
Example:
String data{Alice:} = "123";
output.println("this is it" + data);
note: more appropriate tag would be JIF, but I can not add tags yet.
Found a partial answer. For the moment I am working in a code stub provided by a friend.
Here there is an output stream created with the lowest restrictions ({}, public):
PrintStream[{}] output = declassify(runtime.stdout(new label{}), {});
if (output == null) return;
Then the declassify(...) must be called to declassify to public and afterwards print.
Therefore later on in the program:
int{Alice:} iAlice = 3;
int aliceDec;
aliceDec = declassify(ziAlice, {});
output.println("aliceDec: " + aliceDec);