I have a device that comunicate with the program via rs232.Device send a message and the program read a byte by byte and put in the buffer so another thread parse the buffer.
Problem is that in the message i will have a 0x00 byte {null element for fifo buffer} so i can`t enter that element in the fifo.How to solve that problem.
I use
BlockingQueue<Byte> queue = new ArrayBlockingQueue<>(1000);
For entering byte in the fifo:
public void serialEvent(jssc.SerialPortEvent event) {
if (event.isRXCHAR()) {//If data is available
try {
buffer = serialPort.readBytes();
System.out.println(bytesToHex(buffer) + " event");
for (int i = 0; i < buffer.length; i++) {
queue.add(buffer[i]);
}
} catch (SerialPortException ex) {
System.out.println(ex);
}
And for poll the element
byte stx = queue.poll();
How to enter null elements because message will have a null bytes?
the code for parsing(thread for parsing):
public void run() {
while (true) {
while (!queue.isEmpty()) {
System.out.println(queue.size() + " 1 proverka");
sb = new StringBuilder();
byte stx = queue.poll();
System.out.println(byteToHex(stx) + " parser");
if (stx == 0x02) {
sb.append(String.format("%02X ", stx));
System.out.println(queue.size() + " 2 proverka");
for (int i = 0; i < 3; i++) {
System.out.println(queue.size() + " 3 proverka " + i + " krug");
len[i] = queue.poll();
System.out.println(byteToHex(len[i]) + " parser");
output:
02 event
0000 event
01 event
4 1 proverka
77 event
2 parser
03 event
75 event
6 2 proverka
6 3 proverka 0 krug
Exception in thread "Thread-1" java.lang.NullPointerException
at es.moduli.ingenico_card_reader.Ingenico_Card_Reader$SerialParser.run(Ingenico_Card_Reader.java:127)
edited with my custom byte class
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package es.moduli.ingenico_card_reader;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import jssc.SerialPort;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;
/**
*
* #author GiGo
*/
public class Ingenico_Card_Reader {
static SerialPort serialPort;
static BlockingQueue<CustomByte> queue = new ArrayBlockingQueue<>(1000);
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public void open() {
serialPort = new SerialPort("COM4");
try {
serialPort.openPort();//Open port
serialPort.setParams(9600, 8, 1, 0);//Set params
int mask = SerialPort.MASK_RXCHAR;//Prepare mask
serialPort.setEventsMask(mask);//Set mask
serialPort.addEventListener(new SerialPortEvent());//Add SerialPortEventListener
} catch (SerialPortException ex) {
System.out.println(ex);
}
SerialParser parser = new SerialParser();
parser.start();
}
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
public static String byteToHex(byte b) {
int i = b & 0xFF;
return Integer.toHexString(i);
}
public static int byteToIntBE(byte[] b) {
ByteBuffer bb = ByteBuffer.wrap(b);
bb.order(ByteOrder.BIG_ENDIAN);
int result = bb.getInt();
return result;
}
public static void sleep(long i) {
try {
Thread.sleep(i);
} catch (Exception e) {
}
}
public static String hexString(byte[] b) {
StringBuilder d = new StringBuilder(b.length * 2);
for (int i = 0; i < b.length; i++) {
char hi = Character.forDigit(b[i] >> 4 & 0xF, 16);
char lo = Character.forDigit(b[i] & 0xF, 16);
d.append(Character.toUpperCase(hi));
d.append(Character.toUpperCase(lo));
}
return d.toString();
}
public static class SerialPortEvent implements SerialPortEventListener {
byte buffer[];
#Override
public void serialEvent(jssc.SerialPortEvent event) {
if (event.isRXCHAR()) {//If data is available
//if (event.getEventValue() == 1) {//Check bytes count in the input buffer
//Read data, if 1 byte available
try {
buffer = serialPort.readBytes();
System.out.println(bytesToHex(buffer) + " event");
for (int i = 0; i < buffer.length; i++) {
queue.add(new CustomByte(buffer[i], true));
}
} catch (SerialPortException ex) {
System.out.println(ex);
}
}
// }
}
}
public static class SerialParser extends Thread {
StringBuilder sb = new StringBuilder();
Byte len[];
int len_mess = 0;
Byte mess[];
#Override
public void run() {
while (true) {
while (!queue.isEmpty()) {
System.out.println(queue.size() + " 1 proverka");
sb = new StringBuilder();
byte stx = queue.poll().getBufferByte();
System.out.println(byteToHex(stx) + " parser");
if (stx == 0x02) {
sb.append(String.format("%02X ", stx));
System.out.println(queue.size() + " 2 proverka");
for (int i = 0; i < 3; i++) {
System.out.println(queue.size() + " 3 proverka " + i + " krug");
len[i] = queue.poll().getBufferByte();
System.out.println(byteToHex(len[i]) + " parser");
//sb.append(String.format("%02X ", len[i]));
}
len_mess = (256 * 256 * len[0]) + (256 * len[1]) + (len[2]);
for (int i = 0; i < len_mess; i++) {
mess[i] = queue.poll().getBufferByte();
System.out.println(byteToHex(mess[i]) + "parser");
sb.append(String.format("%02X ", mess[i]));
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
System.out.println(ex.getMessage());
}
}
byte etx = queue.poll().getBufferByte();
System.out.println(byteToHex(etx) + "parser");
if (etx == 0x03) {
sb.append(String.format("%02X ", etx));
System.out.println(sb.toString());
} else {
System.out.println("NOT ETX");
}
} else {
System.out.println("NOT STX");
}
System.out.println(sb.toString());
}
}
}
}
}
THE SAME ERROR
02 event
0000017703 event
6 1 proverka
2 parser
75 event
6 2 proverka
6 3 proverka 0 krug
Exception in thread "Thread-1" java.lang.NullPointerException
at es.moduli.ingenico_card_reader.Ingenico_Card_Reader$SerialParser.run(Ingenico_Card_Reader.java:129)
A BlockingQueue<Byte> can have (byte) 0x00 values however it is very inefficient way to deal with a stream of bytes. This will create around 16 bytes of garbage for each actual byte sent.
Another approach is to use a Pipe stream which is designed for this sort of task.
PipedOutputStream out = new PipedOutputStream();
PipedInputStream in = new PipedInputStream(out);
In the thread reading from the RS232, you can write the bytes you read to the out and in another thread you can process this by reading from in.
This approach doesn't create any garbage on a per byte basis.
Your can wrap the Byte class with your custom Byte class:
public class CustomByte {
private Byte bufferByte;
private boolean isNull;
// Add constructor, getters/setters as required
}
and change the queue type to use this type.
Then when you encounter a null byte just add a CustomByte object with the flag on:
queue.add(new CustomByte(buffer[i], true))
then when polling CustomByte objects you can query the isNull flag
Related
I tried to run the sample code from:
https://learn.microsoft.com/en-us/azure/cognitive-services/speech-service/how-to-async-conversation-transcription
implementing helper class from:
https://github.com/Azure-Samples/cognitive-services-speech-sdk/blob/master/samples/java/jre/console/src/com/microsoft/cognitiveservices/speech/samples/console/WavStream.java
with some slight modifications so that it can read in wav files not limited to 16kHz 16bit single channel, and when I run it, this comes up:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Conversation transcriber canceled:SessionId:b2496d2c13424b3ba3138f2c8ce0893f ResultId:258796dbc69d491786f3ccdd8ec708d6 CancellationReason:Error CancellationErrorCode:ConnectionFailure Error details:<Connection failed (no connection to the remote host). Internal error: 1. Error details: 11001. Please check network connection, firewall setting, and the region name used to create speech factory. SessionId: b2496d2c13424b3ba3138f2c8ce0893f
Conversation transcriber stopped:SessionId: b2496d2c13424b3ba3138f2c8ce0893f.
I'm pretty sure that the API key and the region setup are correct and running and the Internet configuration isn't having any problem.
Here are the codes:
Main.java:
package speechsdk.quickstart;
import com.azure.core.util.polling.PollerFlux;
import com.azure.core.util.polling.SyncPoller;
import com.microsoft.cognitiveservices.speech.*;
import com.microsoft.cognitiveservices.speech.audio.*;
import com.microsoft.cognitiveservices.speech.remoteconversation.RemoteConversationTranscriptionClient;
import com.microsoft.cognitiveservices.speech.remoteconversation.RemoteConversationTranscriptionOperation;
import com.microsoft.cognitiveservices.speech.remoteconversation.RemoteConversationTranscriptionResult;
import com.microsoft.cognitiveservices.speech.transcription.Conversation;
import com.microsoft.cognitiveservices.speech.transcription.ConversationTranscriber;
import com.microsoft.cognitiveservices.speech.transcription.ConversationTranscriptionResult;
import javax.sound.sampled.AudioFileFormat;
import java.io.FileInputStream;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
* Quickstart: recognize speech using the Speech SDK for Java.
*/
public class Main {
/**
* #param args Arguments are ignored in this sample.
*/
public static void main(String[] args) {
try {
// Create the speech config object
SpeechConfig speechConfig = SpeechConfig.fromSubscription("APIKEY", "SERVICEREGION");
speechConfig.setProperty("ConversationTranscriptionInRoomAndOnline", "true");
// Set the property for asynchronous transcription
speechConfig.setServiceProperty("transcriptionMode", "Async", ServicePropertyChannel.UriQueryParameter);
// Set the property for real-time plus asynchronous transcription
//speechConfig.setServiceProperty("transcriptionMode", "RealTimeAndAsync", ServicePropertyChannel.UriQueryParameter);
// pick a conversation Id that is a GUID.
String conversationId = UUID.randomUUID().toString();
// Create a Conversation
Conversation conversation = new Conversation(speechConfig, conversationId);
// Create an audio stream from a wav file or from the default microphone if you want to stream live audio from the supported devices
// Replace with your own audio file name and Helper class which implements AudioConfig using PullAudioInputStreamCallback
WavStream wavStream = new WavStream(new FileInputStream("sample.wav"));
PullAudioInputStreamCallback wavfilePullStreamCallback = wavStream;
// Create an audio stream format assuming the file used above is 16Khz, 16 bits and 8 channel pcm wav file
//AudioStreamFormat audioStreamFormat = AudioStreamFormat.getWaveFormatPCM((long)16000, (short)16,(short)8);
AudioStreamFormat audioStreamFormat = AudioStreamFormat.getWaveFormatPCM(wavStream.getSamplespersecond(), (short) wavStream.getBitspersample(), (short) wavStream.getChannel());
// Create an input stream
AudioInputStream audioStream = AudioInputStream.createPullStream(wavfilePullStreamCallback, audioStreamFormat);
// Create a conversation transcriber
ConversationTranscriber transcriber = new ConversationTranscriber(AudioConfig.fromStreamInput(audioStream));
// join a conversation
transcriber.joinConversationAsync(conversation);
// Add the event listener for the realtime events
transcriber.transcribed.addEventListener((o, e) -> {
System.out.println("Conversation transcriber Recognized:" + e.toString());
});
transcriber.canceled.addEventListener((o, e) -> {
System.out.println("Conversation transcriber canceled:" + e.toString());
try {
transcriber.stopTranscribingAsync().get();
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (ExecutionException ex) {
ex.printStackTrace();
}
});
transcriber.sessionStopped.addEventListener((o, e) -> {
System.out.println("Conversation transcriber stopped:" + e.toString());
try {
transcriber.stopTranscribingAsync().get();
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (ExecutionException ex) {
ex.printStackTrace();
}
});
// start the transcription.
Future<?> future = transcriber.startTranscribingAsync();
// Create a remote Conversation Transcription client
RemoteConversationTranscriptionClient client = new RemoteConversationTranscriptionClient(speechConfig);
// Get the PollerFlux for the remote operation
PollerFlux<RemoteConversationTranscriptionOperation, RemoteConversationTranscriptionResult> remoteTranscriptionOperation = client.getTranscriptionOperation(conversationId);
// Subscribe to PollerFlux to get the remote operation status
remoteTranscriptionOperation.subscribe(
pollResponse -> {
System.out.println("Poll response status : " + pollResponse.getStatus());
System.out.println("Poll response status : " + pollResponse.getValue().getServiceStatus());
}
);
// Obtain the blocking operation using getSyncPoller
SyncPoller<RemoteConversationTranscriptionOperation, RemoteConversationTranscriptionResult> blockingOperation = remoteTranscriptionOperation.getSyncPoller();
// Wait for the operation to finish
blockingOperation.waitForCompletion();
// Get the final result response
RemoteConversationTranscriptionResult resultResponse = blockingOperation.getFinalResult();
// Print the result
if(resultResponse != null) {
if(resultResponse.getConversationTranscriptionResults() != null) {
for (int i = 0; i < resultResponse.getConversationTranscriptionResults().size(); i++) {
ConversationTranscriptionResult result = resultResponse.getConversationTranscriptionResults().get(i);
System.out.println(result.getProperties().getProperty(PropertyId.SpeechServiceResponse_JsonResult.name()));
System.out.println(result.getProperties().getProperty(PropertyId.SpeechServiceResponse_JsonResult));
System.out.println(result.getOffset());
System.out.println(result.getDuration());
System.out.println(result.getUserId());
System.out.println(result.getReason());
System.out.println(result.getResultId());
System.out.println(result.getText());
System.out.println(result.toString());
}
}
}
System.out.println("Operation finished");
} catch (Exception ex) {
//System.out.println("Unexpected exception: " + ex.getMessage());
ex.printStackTrace();
assert(false);
System.exit(1);
}
}
}
Helper.java:
package speechsdk.quickstart;
import com.microsoft.cognitiveservices.speech.audio.PullAudioInputStreamCallback;
import com.microsoft.cognitiveservices.speech.internal.AudioConfig;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.slf4j.*;
class WavStream extends PullAudioInputStreamCallback {
private final InputStream stream;
private long samplespersecond;
private int bitspersample;
private int channel;
public long getSamplespersecond()
{
return samplespersecond;
}
public int getBitspersample()
{
return bitspersample;
}
public int getChannel()
{
return channel;
}
public WavStream(InputStream wavStream) {
try {
this.stream = parseWavHeader(wavStream);
} catch (Exception ex) {
throw new IllegalArgumentException(ex.getMessage());
}
}
#Override
public int read(byte[] dataBuffer) {
long ret = 0;
try {
ret = this.stream.read(dataBuffer, 0, dataBuffer.length);
} catch (Exception ex) {
System.out.println("Read " + ex);
}
return (int)Math.max(0, ret);
}
#Override
public void close() {
try {
this.stream.close();
} catch (IOException ex) {
// ignored
}
}
// endregion
// region Wav File helper functions
private int ReadInt32(InputStream inputStream) throws IOException {
int n = 0;
for (int i = 0; i < 4; i++) {
n |= inputStream.read() << (i * 8);
}
return n;
}
private long ReadUInt32(InputStream inputStream) throws IOException {
long n = 0;
for (int i = 0; i < 4; i++) {
n |= inputStream.read() << (i * 8);
}
return n;
}
private int ReadUInt16(InputStream inputStream) throws IOException {
int n = 0;
for (int i = 0; i < 2; i++) {
n |= inputStream.read() << (i * 8);
}
return n;
}
public InputStream parseWavHeader(InputStream reader) throws IOException {
// Note: assumption about order of chunks
// Tag "RIFF"
byte data[] = new byte[4];
int numRead = reader.read(data, 0, 4);
ThrowIfFalse((numRead == 4) && (data[0] == 'R') && (data[1] == 'I') && (data[2] == 'F') && (data[3] == 'F'), "RIFF");
// Chunk size
/* int fileLength = */ReadInt32(reader);
// Subchunk, Wave Header
// Subchunk, Format
// Tag: "WAVE"
numRead = reader.read(data, 0, 4);
ThrowIfFalse((numRead == 4) && (data[0] == 'W') && (data[1] == 'A') && (data[2] == 'V') && (data[3] == 'E'), "WAVE");
// Tag: "fmt"
numRead = reader.read(data, 0, 4);
ThrowIfFalse((numRead == 4) && (data[0] == 'f') && (data[1] == 'm') && (data[2] == 't') && (data[3] == ' '), "fmt ");
// chunk format size
long formatSize = ReadInt32(reader);
ThrowIfFalse(formatSize >= 16, "formatSize");
int formatTag = ReadUInt16(reader);
int channels = ReadUInt16(reader);
int samplesPerSec = (int) ReadUInt32(reader);
int avgBytesPerSec = (int) ReadUInt32(reader);
int blockAlign = ReadUInt16(reader);
int bitsPerSample = ReadUInt16(reader);
ThrowIfFalse(formatTag == 1, "PCM"); // PCM
//ThrowIfFalse(channels == 1, "single channel");
channel = channels;
//ThrowIfFalse(samplesPerSec == 16000, "samples per second");
samplespersecond = samplesPerSec;
//ThrowIfFalse(bitsPerSample == 16, "bits per sample");
bitspersample = bitsPerSample;
// Until now we have read 16 bytes in format, the rest is cbSize and is ignored
// for now.
if (formatSize > 16) {
numRead = reader.read(new byte[(int) (formatSize - 16)]);
ThrowIfFalse(numRead == (int)(formatSize - 16), "could not skip extended format");
}
// Second Chunk, data
// tag: data.
numRead = reader.read(data, 0, 4);
//for (byte i : data) System.out.print((char) i);
//System.out.println();
//ThrowIfFalse((numRead == 4) && (data[0] == 'd') && (data[1] == 'a') && (data[2] == 't') && (data[3] == 'a'), "data");
// data chunk size
// Note: assumption is that only a single data chunk
/* int dataLength = */ReadInt32(reader);
numRead = reader.read(data, 0, 4);
while (!((numRead == 4) && (data[0] == 'd') && (data[1] == 'a') && (data[2] == 't') && (data[3] == 'a')))
{
numRead = reader.read(data, 0, 4);
//for (byte i : data) System.out.print((char) i);
//System.out.println();
ReadInt32(reader);
}
//for (byte i : data) System.out.println((char) i);
return reader;
}
private static void ThrowIfFalse(Boolean condition, String message) {
if (!condition) {
throw new IllegalArgumentException(message);
}
}
// endregion
}
Using azure document, if you can please configure the following and provide us the log.
config.setProperty(PropertyId.Speech_LogFilename, "LogfilePathAndName");
By the way, what is the region you are using to do the transcription?
For conversation transcription, the input wave file should be 8 channel, 16 bits and 16 Khz wave file. Try putting a sleep after the following code till you get the session stopped called.
// start the transcription.
Future<?> future = transcriber.startTranscribingAsync();
Also if possible change the following code to
PollerFlux<RemoteConversationTranscriptionOperation, RemoteConversationTranscriptionResult> remoteTranscriptionOperation = client.getTranscriptionOperation(conversationId,5);
Do let us know if it works.
EDIT: I tried this using a multiple file upload, and I got 3 of 4 uploaded files, so it seems that the upload mechanism is only setting the offset too high for the first file.
I found a method for uploading files using the com.sun.net.httpserver library here, but it is not actually detecting any files from the form input. What it does is it finds the "starting point" of uploaded files, represented by List<Integer> offsets and then looks through the file to get bytes from it. The problem is that it sets each part of offsets as a number very close to the end of the form data, so nothing actually gets parsed. Here is my HttpHandler:
package app;
import com.sun.net.httpserver.*;
import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class FormDataHandler implements HttpHandler {
#Override
public void handle(HttpExchange httpExchange) throws IOException {
Headers headers = httpExchange.getRequestHeaders();
String contentType = headers.getFirst("Content-Type");
if(contentType.startsWith("multipart/form-data")){
//found form data
String boundary = contentType.substring(contentType.indexOf("boundary=")+9);
// as of rfc7578 - prepend "\r\n--"
byte[] boundaryBytes = ("\r\n--" + boundary).getBytes(Charset.forName("UTF-8"));
byte[] payload = getInputAsBinary(httpExchange.getRequestBody());
ArrayList<MultiPart> list = new ArrayList<>();
List<Integer> offsets = searchBytes(payload, boundaryBytes, 0, payload.length - 1);
System.out.println(offsets);
for(int idx=0;idx<offsets.size();idx++){
int startPart = offsets.get(idx);
int endPart = payload.length;
if(idx<offsets.size()-1){
endPart = offsets.get(idx+1);
}
byte[] part = Arrays.copyOfRange(payload,startPart,endPart);
//look for header
int headerEnd = indexOf(part,"\r\n\r\n".getBytes(Charset.forName("UTF-8")),0,part.length-1);
/*This conditional is always false because headerEnd is not
found, due to part.length being to small, due to startPart
being too small, due to the current offset being to small*/
if(headerEnd>0) {
MultiPart p = new MultiPart();
byte[] head = Arrays.copyOfRange(part, 0, headerEnd);
String header = new String(head);
// extract name from header
int nameIndex = header.indexOf("\r\nContent-Disposition: form-data; name=");
if (nameIndex >= 0) {
int startMarker = nameIndex + 39;
//check for extra filename field
int fileNameStart = header.indexOf("; filename=");
if (fileNameStart >= 0) {
String filename = header.substring(fileNameStart + 11, header.indexOf("\r\n", fileNameStart));
p.filename = filename.replace('"', ' ').replace('\'', ' ').trim();
p.name = header.substring(startMarker, fileNameStart).replace('"', ' ').replace('\'', ' ').trim();
p.type = PartType.FILE;
} else {
int endMarker = header.indexOf("\r\n", startMarker);
if (endMarker == -1)
endMarker = header.length();
p.name = header.substring(startMarker, endMarker).replace('"', ' ').replace('\'', ' ').trim();
p.type = PartType.TEXT;
}
} else {
// skip entry if no name is found
continue;
}
// extract content type from header
int typeIndex = header.indexOf("\r\nContent-Type:");
if (typeIndex >= 0) {
int startMarker = typeIndex + 15;
int endMarker = header.indexOf("\r\n", startMarker);
if (endMarker == -1)
endMarker = header.length();
p.contentType = header.substring(startMarker, endMarker).trim();
}
//handle content
if (p.type == PartType.TEXT) {
//extract text value
byte[] body = Arrays.copyOfRange(part, headerEnd + 4, part.length);
p.value = new String(body);
} else {
//must be a file upload
p.bytes = Arrays.copyOfRange(part, headerEnd + 4, part.length);
}
list.add(p);
}
}
handle(httpExchange,list);
}else{
//if no form data is present, still call handle method
handle(httpExchange,null);
}
}
public void handle(HttpExchange he, List<MultiPart> parts) throws IOException {
OutputStream os = he.getResponseBody();
String response = "<h1>" + parts.size() + "</h1>";
he.sendResponseHeaders(200, response.length());
os.write(response.getBytes());
os.close();
}
public static byte[] getInputAsBinary(InputStream requestStream) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
byte[] buf = new byte[100000];
int bytesRead=0;
while ((bytesRead = requestStream.read(buf)) != -1){
//while (requestStream.available() > 0) {
// int i = requestStream.read(buf);
bos.write(buf, 0, bytesRead);
}
requestStream.close();
bos.close();
} catch (IOException e) {
}
return bos.toByteArray();
}
/**
* Search bytes in byte array returns indexes within this byte-array of all
* occurrences of the specified(search bytes) byte array in the specified
* range
* borrowed from https://github.com/riversun/finbin/blob/master/src/main/java/org/riversun/finbin/BinarySearcher.java
*
* #param srcBytes
* #param searchBytes
* #param searchStartIndex
* #param searchEndIndex
* #return result index list
*/
public List<Integer> searchBytes(byte[] srcBytes, byte[] searchBytes, int searchStartIndex, int searchEndIndex) {
final int destSize = searchBytes.length;
final List<Integer> positionIndexList = new ArrayList<Integer>();
int cursor = searchStartIndex;
while (cursor < searchEndIndex + 1) {
int index = indexOf(srcBytes, searchBytes, cursor, searchEndIndex);
if (index >= 0) {
positionIndexList.add(index);
cursor = index + destSize;
} else {
cursor++;
}
}
return positionIndexList;
}
/**
* Returns the index within this byte-array of the first occurrence of the
* specified(search bytes) byte array.<br>
* Starting the search at the specified index, and end at the specified
* index.
* borrowed from https://github.com/riversun/finbin/blob/master/src/main/java/org/riversun/finbin/BinarySearcher.java
*
* #param srcBytes
* #param searchBytes
* #param startIndex
* #param endIndex
* #return
*/
public int indexOf(byte[] srcBytes, byte[] searchBytes, int startIndex, int endIndex) {
if (searchBytes.length == 0 || (endIndex - startIndex + 1) < searchBytes.length) {
return -1;
}
int maxScanStartPosIdx = srcBytes.length - searchBytes.length;
final int loopEndIdx;
if (endIndex < maxScanStartPosIdx) {
loopEndIdx = endIndex;
} else {
loopEndIdx = maxScanStartPosIdx;
}
int lastScanIdx = -1;
label: // goto label
for (int i = startIndex; i <= loopEndIdx; i++) {
for (int j = 0; j < searchBytes.length; j++) {
if (srcBytes[i + j] != searchBytes[j]) {
continue label;
}
lastScanIdx = i + j;
}
if (endIndex < lastScanIdx || lastScanIdx - i + 1 < searchBytes.length) {
// it becomes more than the last index
// or less than the number of search bytes
return -1;
}
return i;
}
return -1;
}
public static class MultiPart {
public PartType type;
public String contentType;
public String name;
public String filename;
public String value;
public byte[] bytes;
}
public enum PartType{
TEXT,FILE
}
}
And here is my form:
<form action="http://localhost:8080/upl" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="Submit">
</form>
Does anybody know why this won't work? If not, is there a better option for HttpServer file uploads? I tried the Apache Commons API, but that didn't work either.
I was using processing in netbeans to play a movie on an array of ledstrips and I am using OPC.class for ledstrip fadecandy mapping. This code works on the processing sketch, but when I tried to use it on netbeans the loadpixel() in draw() method of OPC.java throws a nullpointer exception.
Stacktrace:
Exception in thread "Animation Thread" java.lang.NullPointerException
at processing.core.PApplet.loadPixels(PApplet.java:10625)
at com.processing.OPC.draw(OPC.java:139)
at com.processing.Video.draw(Video.java:62)
at processing.core.PApplet.handleDraw(PApplet.java:2402)
at processing.awt.PSurfaceAWT$12.callDraw(PSurfaceAWT.java:1527)
at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:316)
Video.java
public class Video extends PApplet
{
OPC opc;
Movie movie;
public static void main(String args[])
{
PApplet.main(new String[] { "--present", "com.processing.Video" });
}
public void settings()
{
size(600, 240);
}
public void setup()
{
opc = new OPC(this, "192.168.15.10", 7890);
for(int i=0; i<24; i++) {
opc.ledStrip(i * 60, 60,
300, i * 240 / 24 + 240 / 48, 240 / 24, PI, false);
}
movie = new Movie(this, "waffle.mp4");
movie.loop();
}
public void movieEvent(Movie m)
{
m.read();
}
#Override
public void draw()
{
if (movie.available() == true) {
movie.read();
}
image(movie, 0, 0, width, height);
}
}
OPC.java
public class OPC extends PApplet implements Runnable
{
Thread thread;
Socket socket;
OutputStream output, pending;
String host;
int port;
int height = 240;
int width = 600;
int[] pixelLocations;
byte[] packetData;
byte firmwareConfig;
String colorCorrection;
boolean enableShowLocations;
PApplet parent;
OPC(PApplet parent, String host, int port)
{
this.host = host;
this.port = port;
thread = new Thread(this);
thread.start();
this.enableShowLocations = true;
registerMethod("draw", this);
}
public void led(int index, int x, int y){
if (pixelLocations == null) {
pixelLocations = new int[index + 1];
} else if (index >= pixelLocations.length) {
pixelLocations = Arrays.copyOf(pixelLocations, index + 1);
}
pixelLocations[index] = x + 600 * y;
}
public void ledStrip(int index, int count, float x, float y, float spacing, float angle, boolean reversed)
{
float s = sin(angle);
float c = cos(angle);
for (int i = 0; i < count; i++) {
led(reversed ? (index + count - 1 - i) : (index + i),
(int)(x + (i - (count-1)/2.0) * spacing * c + 0.5),
(int)(y + (i - (count-1)/2.0) * spacing * s + 0.5));
}
}
void showLocations(boolean enabled)
{
enableShowLocations = enabled;
}
void setColorCorrection(String s)
{
colorCorrection = s;
sendColorCorrectionPacket();
}
void sendFirmwareConfigPacket()
{
if (pending == null) {
return;
}
byte[] packet = new byte[9];
packet[0] = (byte)0x00; // Channel (reserved)
packet[1] = (byte)0xFF; // Command (System Exclusive)
packet[2] = (byte)0x00; // Length high byte
packet[3] = (byte)0x05; // Length low byte
packet[4] = (byte)0x00; // System ID high byte
packet[5] = (byte)0x01; // System ID low byte
packet[6] = (byte)0x00; // Command ID high byte
packet[7] = (byte)0x02; // Command ID low byte
packet[8] = (byte)firmwareConfig;
try {
pending.write(packet);
} catch (Exception e) {
dispose();
}
}
void sendColorCorrectionPacket()
{
if (colorCorrection == null) {
return;
}
if (pending == null) {
return;
}
byte[] content = colorCorrection.getBytes();
int packetLen = content.length + 4;
byte[] header = new byte[8];
header[0] = (byte)0x00; // Channel (reserved)
header[1] = (byte)0xFF; // Command (System Exclusive)
header[2] = (byte)(packetLen >> 8); // Length high byte
header[3] = (byte)(packetLen & 0xFF); // Length low byte
header[4] = (byte)0x00; // System ID high byte
header[5] = (byte)0x01; // System ID low byte
header[6] = (byte)0x00; // Command ID high byte
header[7] = (byte)0x01; // Command ID low byte
try {
pending.write(header);
pending.write(content);
} catch (Exception e) {
dispose();
}
}
public void draw()
{
if (pixelLocations == null) {
return;
}
if (output == null) {
return;
}
int numPixels = pixelLocations.length;
int ledAddress = 4;
setPixelCount(numPixels);
println("pixel loading");
loadPixels();
println("pixel loaded123");
for (int i = 0; i < numPixels; i++) {
int pixelLocation = pixelLocations[i];
int pixel = pixels[pixelLocation];
packetData[ledAddress] = (byte)(pixel >> 16);
packetData[ledAddress + 1] = (byte)(pixel >> 8);
packetData[ledAddress + 2] = (byte)pixel;
ledAddress += 3;
if (true) {
pixels[pixelLocation] = 0xFFFFFF ^ pixel;
}
}
writePixels();
if (enableShowLocations) {
updatePixels();
print("a");
}
}
void setPixelCount(int numPixels)
{
int numBytes = 3 * numPixels;
int packetLen = 4 + numBytes;
if (packetData == null || packetData.length != packetLen) {
// Set up our packet buffer
packetData = new byte[packetLen];
packetData[0] = (byte)0x00;
packetData[1] = (byte)0x00;
packetData[2] = (byte)(numBytes >> 8);
packetData[3] = (byte)(numBytes & 0xFF);
}
}
void setPixel(int number, int c)
{
println("set");
int offset = 4 + number * 3;
if (packetData == null || packetData.length < offset + 3) {
setPixelCount(number + 1);
}
packetData[offset] = (byte) (c >> 16);
packetData[offset + 1] = (byte) (c >> 8);
packetData[offset + 2] = (byte) c;
}
int getPixel(int number)
{
println("get");
int offset = 4 + number * 3;
if (packetData == null || packetData.length < offset + 3) {
return 0;
}
return (packetData[offset] << 16) | (packetData[offset + 1] << 8) | packetData[offset + 2];
}
void writePixels()
{
println("write");
if (packetData == null || packetData.length == 0) {
return;
}
if (output == null) {
return;
}
try {
output.write(packetData);
} catch (Exception e) {
dispose();
}
}
public void dispose()
{
if (output != null) {
println("Disconnected from OPC server");
}
socket = null;
output = pending = null;
}
public void run()
{
println("?");
if(output == null) { // No OPC connection?
try { // Make one!
socket = new Socket(host, port);
socket.setTcpNoDelay(true);
pending = socket.getOutputStream();
println("Connected to OPC server");
sendColorCorrectionPacket();
sendFirmwareConfigPacket();
output = pending;
} catch (ConnectException e) {
dispose();
} catch (IOException e) {
dispose();
}
}
try {
Thread.sleep(500);
}
catch(InterruptedException e) {
}
}
}
You should only have one class that extends PApplet.
Think of that class as your "main" class. Any other classes that need to use Processing functions will need an instance of that main class in order to access Processing functions. You can pass it in using the this keyword.
In fact, you're already doing that- notice that you pass this into your OPC class, and then store it in the parent parameter. You just never do anything with that parameter.
So step 1 is to remove the extends PApplet from your OBC class:
public class OPC implements Runnable
This will cause some compilation errors. That's okay, we'll fix them later.
Step 2 is to actually store the PApplet parent parameter in a class-level variable.
OPC(PApplet parent, String host, int port){
this.parent = parent;
//rest of constructor
Now that you have that, step 3 is to fix any compilation errors by using the parent variable to access Processing functions.
parent.println("pixel loading");
parent.loadPixels();
More info can be found in the Processing in eclipse tutorial. It's for eclipse, but the same principles apply in netbeans.
I want to take real-time data using modbus tcp/ip simulator for filling of a tank that uses port no 502.
How can I write a code in java to get the holding register value from the simulator and also I want to control the values of it?
If you use a Modbus library like this one most of the work is already done for you.
ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder("localhost").build();
ModbusTcpMaster master = new ModbusTcpMaster(config);
CompletableFuture<ReadHoldingRegistersResponse> future =
master.sendRequest(new ReadHoldingRegistersRequest(0, 10), 0);
future.thenAccept(response -> {
System.out.println("Response: " + ByteBufUtil.hexDump(response.getRegisters()));
ReferenceCountUtil.release(response);
});
import java.io.* ;
import java.net.* ;
import java.util.*;
public class Modcli {
public static void main(String argv[]) {
if (argv.length < 4) {
System.out.println("usage: java test3 dns_name unit reg_no num_regs");
System.out.println("eg java test3 aswales8.modicon.com 5 0 10");
return;
}
try {
String ip_adrs = argv[0];
int unit = Integer.parseInt(argv[1]);
int reg_no = Integer.parseInt(argv[2]);
int num_regs = Integer.parseInt(argv[3]);
System.out.println("ip_adrs = "+ip_adrs+" unit = "+unit+" reg_no = "+
reg_no+" num_regs = "+num_regs);
// set up socket
Socket es = new Socket(ip_adrs,502);
OutputStream os= es.getOutputStream();
FilterInputStream is = new BufferedInputStream(es.getInputStream());
byte obuf[] = new byte[261];
byte ibuf[] = new byte[261];
int c = 0;
int i;
// build request of form 0 0 0 0 0 6 ui 3 rr rr nn nn
for (i=0;i<5;i++) obuf[i] = 0;
obuf[5] = 6;
obuf[6] = (byte)unit;
obuf[7] = 3;
obuf[8] = (byte)(reg_no >> 8);
obuf[9] = (byte)(reg_no & 0xff);
obuf[10] = (byte)(num_regs >> 8);
obuf[11] = (byte)(num_regs & 0xff);
// send request
os.write(obuf, 0, 12);
// read response
i = is.read(ibuf, 0, 261);
if (i<9) {
if (i==0) {
System.out.println("unexpected close of connection at remote end");
} else {
System.out.println("response was too short - "+i+" chars");
}
} else if (0 != (ibuf[7] & 0x80)) {
System.out.println("MODBUS exception response - type "+ibuf[8]);
} else if (i != (9+2*num_regs)) {
System.out.println("incorrect response size is "+i+
" expected"+(9+2*num_regs));
} else {
for (i=0;i<=2;i++) {
int w = (ibuf[0+i+i]<<8) + ibuf[1+i+i];
System.out.println("word "+i+" = "+w);
}
for (i=3;i<=5;i++) {
int w = (ibuf[i+3]) ;
System.out.println("word "+i+" = "+w);
}
for (i=0;i<num_regs;i++) {
int w = (ibuf[9+i+i]<<8) + ibuf[10+i+i];
System.out.println("word "+i+" = "+w);
}
}
// close down
es.close();
} catch (Exception e) {
System.out.println("exception :"+e);
}
}
}
ObjectInputStream blocks when created until it recieves a serial input stream ans verifies it. I was trying to make my first program using sockets through it and found this. I used a dummy object so that it doesn't block. The code is here:
import java.io.*;
import java.net.*;
import java.util.*;
class Dummy implements Serializable {
}
class X_Int implements Serializable {
int x;
}
class Server {
public static void main(String args[]) throws Exception {
ServerSocket ss = new ServerSocket(5879);
Socket client = ss.accept();
ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
out.writeObject(new Dummy());
ObjectInputStream in = new ObjectInputStream(client.getInputStream());
in.readObject();
out.flush();
out.writeObject(new Date());
out.flush();
out.close();
}
}
class Client {
public static void main(String args[]) throws Exception {
Socket server = new Socket("localhost", 5879);
ObjectOutputStream out = new ObjectOutputStream(server.getOutputStream());
out.writeObject(new Dummy());
ObjectInputStream in = new ObjectInputStream(server.getInputStream());
in.readObject();
out.flush();
Date d = (Date)in.readObject();
System.out.println(d);
}
}
Is this the right way. Please comment.
You just need to flush() the output before creating the object input stream.
You don't need to send dummy objects.
A better way is to get rid of the cause of blocking in the first place. Use these classes instead on both ends, if you can:
public class ObjInputStream extends ObjectInputStream {
/**
* #param in
* #throws IOException
*/
public ObjInputStream(InputStream in) throws IOException {
super(in);
}
/* (non-Javadoc)
* #see java.io.ObjectInputStream#readStreamHeader()
*/
#Override
protected void readStreamHeader() throws IOException, StreamCorruptedException {
}
}
and
public class ObjOutputStream extends ObjectOutputStream {
/**
* #param out
* #throws IOException
*/
public ObjOutputStream(OutputStream out) throws IOException {
super(out);
}
/* (non-Javadoc)
* #see java.io.ObjectOutputStream#writeStreamHeader()
*/
#Override
protected void writeStreamHeader() throws IOException {
}
}
This removes the functions which are called to ascertain stream version info and such.
Additionally, as you are using TCP packets, IP fragmentation will cause your objects not be received 'whole' on the other end -- TCP is a stream socket. What you need is an additional framing input / output class. Luckily, I already coded this :)
/**
*
*/
package objtest;
import java.io.IOException;
import java.io.InputStream;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.Queue;
import kokuks.KokuKS;
/**
* UnrealConceptTest - FramedInputStream
* #version 1.0
*/
public class FramedInputStream extends InputStream {
public static final int INITIAL_BUFFER_SIZE = 8 << 1;
public static final int FRAME_HEADER_1 = 0xBEEFFACE;
public static final int FRAME_HEADER_2 = 0xFACEBEEF;
public static final byte[] HEADER_BYTES = new byte[4 * 2];
protected static final byte[] CURR_HEADER_BUFF = new byte[HEADER_BYTES.length];
static {
ByteBuffer b = ByteBuffer.allocateDirect(8);
b.putInt(FRAME_HEADER_1);
b.putInt(FRAME_HEADER_2);
ByteBuffer b2 = (ByteBuffer) b.flip();
b2.get(HEADER_BYTES, 0, 4);
b2.get(HEADER_BYTES, 3, 4);
}
protected int size = 0;
protected int chain = 0;
protected boolean inFrame = false;
protected boolean readingSize = false;
protected int sizePos = 0;
protected int dbgput = 0;
protected ByteBuffer bb = ByteBuffer.allocateDirect(INITIAL_BUFFER_SIZE);
protected Queue<ByteBuffer> bbq = new ArrayDeque<ByteBuffer>();
protected ByteBuffer currBuff = null;
protected final boolean recoverFromError;
/**
*
*/
public FramedInputStream(boolean recoverFromError) {
this.recoverFromError = recoverFromError;
}
public FramedInputStream() {
this(true);
}
protected boolean ensureFramebufferCapacity(int min) {
int mymin = 1 << min;
if (mymin <= bb.capacity()) return false;
int num = bb.capacity();
while (num < mymin) num <<= 1;
ByteBuffer bb2 = ByteBuffer.allocateDirect(num);
// copy old data into new bytebuffer
int bb_pos = bb.position();
bb.rewind();
bb2.put(bb);
bb = bb2;
if (KokuKS.DEBUG_MODE) System.out.println("modified buffer size to: " + num);
return true;
}
/**
* #return the recoverFromError
*/
public boolean isRecoverFromError() {
return recoverFromError;
}
/* (non-Javadoc)
* #see java.io.InputStream#read()
*/
#Override
public int read() throws IOException {
if (currBuff == null || !currBuff.hasRemaining()) return -1;
byte b = currBuff.get();
//System.out.println("data: " + b);
return b;
}
public void putBuffer(ByteBuffer source) {
ensureFramebufferCapacity(bb.capacity() + source.remaining());
while (source.hasRemaining()) {
putByte(source.get());
}
}
public boolean checkCompleteFrame() {
return !bbq.isEmpty();
}
/* (non-Javadoc)
* #see java.io.InputStream#available()
*/
#Override
public int available() throws IOException {
return currBuff != null ? currBuff.remaining() : 0;
}
public int read(byte[] data) {
if (currBuff == null || !currBuff.hasRemaining()) {
return -1;
}
if (data.length > currBuff.remaining()) {
throw new BufferUnderflowException();
}
currBuff.get(data);
//System.out.println("data: " + new String(data));
return data.length;
}
public boolean nextFrame() {
ByteBuffer bbf = bbq.poll();
if (bbf != null) {
/*
System.out.println("bbf limit: " + bbf.limit());
System.out.println("bbf pos: " + bbf.position());
System.out.println("bbf data: " + new String(bbf.array()));
*/
//byte[] data = bbf.array();
//for (int i = 0; i < data.length; i++) {
// byte by = data[i];
// System.out.println("b: " + (by > 32 ? new String(new byte[] {by}) : "??") + ", " + by);
//}
currBuff = ByteBuffer.allocateDirect(bbf.limit());
currBuff.put(bbf).flip();
bbf.rewind();
/*
System.out.println("currbuf limit: " + currBuff.limit());
System.out.println("currbuf pos: " + currBuff.position());
System.out.println("currbuf data: " + new String(currBuff.array()));
*/
currBuff.rewind();
currBuff.position(1);
return true;
}
return false;
}
public void putByte(byte b) {
//System.out.println("pb b: " + ObjTest.getByteStr(b));
if (recoverFromError || !inFrame) {
if (b == HEADER_BYTES[chain++]) {
if (chain >= (HEADER_BYTES.length)) {
if (KokuKS.DEBUG_MODE) System.out.println("got header!" + (inFrame ? " (recovered)" : ""));
// we have a header! hurrah.
inFrame = true;
sizePos = 0;
size = 0;
readingSize = true;
chain = 0;
bb.clear();
}
} else {
chain = 0;
}
}
if (inFrame) {
if (readingSize) {
size += (b & 0xFF) << ((8 * 3) - (8 * sizePos));
//System.out.println("new size: " + size);
sizePos++;
if (sizePos >= 4) {
// we've read the size :)
readingSize = false;
sizePos = 0;
ensureFramebufferCapacity(size);
bb.clear();
bb.limit(size); // set buffer limit to size
//System.out.println("bb limit set to: " + bb.limit());
}
} else {
//System.out.println("put: " + dbgput++ + ", " + ObjTest.getByteStr(b));
bb.put(b);
if (!bb.hasRemaining()) {
bb.flip();
//System.out.println("bb limit after flip(): " + bb.limit());
//System.out.println("bblimit: " + bb.limit());
ByteBuffer newbuf = ByteBuffer.allocateDirect(bb.limit());
newbuf.put(bb).flip(); //we have to flip this
bbq.offer(newbuf);
//byte[] data = newbuf.array();
//for (int i = 0; i < newbuf.limit(); i++) {
// byte by = data[i];
// System.out.println("b: " + (by > 32 ? new String(new byte[] {by}) : "??") + ", " + by);
//}
inFrame = false;
readingSize = false;
size = 0;
sizePos = 0;
chain = 0;
bb.clear();
if (KokuKS.DEBUG_MODE) System.out.println("FIS: complete object");
//System.out.println("FIS: newbuf: " + new String(newbuf.array(), 0, newbuf.limit()));
}
}
}
}
}
and
/**
*
*/
package objtest;
import java.io.IOException;
import java.nio.ByteBuffer;
import koku.util.io.ByteBufferOutputStream;
/**
* UnrealConceptTest - FramedOutputStream
* #version 1.0
* #author Chris Dennett
*/
public class FramedOutputStream extends ByteBufferOutputStream {
public static final int FRAME_HEADER_1 = 0xBEEFFACE;
public static final int FRAME_HEADER_2 = 0xFACEBEEF;
public static final byte[] HEADER_BYTES = new byte[4 * 2];
public static final byte[] CURR_HEADER_BUFF = new byte[HEADER_BYTES.length];
/* We pad the beginning of our buffer so that we can write the frame
* length when the time comes. */
protected static final byte[] SIZE_PAD = new byte[4];
static {
ByteBuffer b = ByteBuffer.allocate(8);
b.putInt(FRAME_HEADER_1);
b.putInt(FRAME_HEADER_2);
ByteBuffer b2 = (ByteBuffer) b.flip();
b2.get(HEADER_BYTES, 0, 4);
b2.get(HEADER_BYTES, 3, 4);
}
/**
*
*/
public FramedOutputStream() {
try {
write(HEADER_BYTES);
write(SIZE_PAD);
} catch (IOException e) {
System.out.println("Couldn't write header padding!");
}
}
/* (non-Javadoc)
* #see koku.util.io.ByteBufferOutputStream#flip()
*/
#Override
public ByteBuffer flip() {
// flip the buffer which will limit it to it's current position
super.flip();
// then write the frame length and rewind back to the start of the
// buffer so that all the data is available
_buffer.position(11);
int size = _buffer.remaining();
//System.out.println("remaining after complete header: " + size);
_buffer.position(7);
//System.out.println("remaining after frameheader: " + _buffer.remaining());
putSizeAsBytes(size, _buffer);
//System.out.println("written size: " + size);
// System.out.println("buffer limit: " + _buffer.limit());
//System.out.println("_buffer: " + new String( _buffer.array(), 0, _buffer.limit()));
_buffer.position(11);
// System.out.println("_buffer11: " + ObjTest.getByteStr(_buffer.get()));
//System.out.println("_buffer12: " + ObjTest.getByteStr(_buffer.get()));
//System.out.println("_buffer13: " + ObjTest.getByteStr(_buffer.get()));
//System.out.println("_buffer14: " + ObjTest.getByteStr(_buffer.get()));
_buffer.rewind();
//_buffer.rewind();
//while (_buffer.hasRemaining()) {
// byte b = _buffer.get();
// System.out.println("b: " + (b > 32 ? new String(new byte[] {b}) : "??") + ", " + b);
//}
_buffer.rewind();
return _buffer;
}
/* (non-Javadoc)
* #see koku.util.io.ByteBufferOutputStream#reset()
*/
#Override
public void reset() {
super.reset();
try {
write(HEADER_BYTES);
write(SIZE_PAD);
} catch (IOException e) {
System.out.println("Couldn't write header padding!");
}
}
public static void putSizeAsBytes(int size, ByteBuffer bb) {
//System.out.println("putSizeAsBytes: given size: " + size);
// encode
for (int i = 0; i < 4; i++) {
bb.put((byte)((size >>> ((8 * 3) - (8 * i))) & 0xFF));
}
}
}
BBOS:
//
// $Id: ByteBufferOutputStream.java 5829 2009-06-20 21:09:34Z mdb $
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2009 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package misc;
import java.io.OutputStream;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import org.apache.mina.core.buffer.IoBuffer;
/**
* Stores output in an {#link ByteBuffer} that grows automatically to accommodate the data.
*/
public class ByteBufferOutputStream extends OutputStream
{
/**
* Creates a new byte buffer output stream.
*/
public ByteBufferOutputStream ()
{
_buffer = IoBuffer.allocate(INITIAL_BUFFER_SIZE);
}
/**
* Returns a reference to the underlying buffer.
*/
public IoBuffer getBuffer ()
{
return _buffer;
}
/**
* Flips and returns the buffer. The returned buffer will have a position of zero and a limit
* equal to the number of bytes written. Call {#link #reset} to reset the buffer before
* writing again.
*/
public IoBuffer flip ()
{
return _buffer.flip();
}
/**
* Resets our internal buffer.
*/
public void reset ()
{
_buffer.clear();
}
#Override // documentation inherited
public void write (int b)
{
try {
_buffer.put((byte)b);
} catch (BufferOverflowException boe) {
expand(1);
_buffer.put((byte)b);
}
}
#Override // documentation inherited
public void write (byte[] b, int off, int len)
{
// sanity check the arguments
if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) > b.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return;
}
try {
_buffer.put(b, off, len);
} catch (BufferOverflowException boe) {
expand(len);
_buffer.put(b, off, len);
}
}
/**
* Expands our buffer to accomodate the specified capacity.
*/
protected final void expand (int needed)
{
_buffer.expand(needed);
}
/** The buffer in which we store our frame data. */
protected IoBuffer _buffer;
/** The default initial size of the internal buffer. */
protected static final int INITIAL_BUFFER_SIZE = 32;
}