Env: Windows 7, java 1.8, default OS encodings
I'm trying to read a byte stream of currency market data from a socket to a file, and then play that file back to simulate the market over a fixed period; however, the file has a few malformed bytes, seemingly at random.
Below, I outline the problem with metacode, where the notation "..." indicates skipped irrelevant or boilerplate code.
Bytes are coming over the socket, and I'm reading them with a non-blockingNIO
selector, then writing to disk via BufferedOutputStream
:
class SocketReadDiskWrite implements Runnable{
...
blobWriter = new BufferedOutputStream(new FileOutputStream(blobFileName));
sc = SocketChannel.open(addr)
sc.configureBlocking(false);
And then in the run()
method, when the selector deems the socket readable,
public void run(){
...
while(keyIterator.hasNext())
{
SelectionKey key = keyIterator.next();
if (key.isReadable()) {
if(bytesRead == -1)
{
connected = false;
logger.warn("no bytes to read");
break;
}
readBuffer.flip();
// Write bytes from socket to file, then rewind and process data
while (readBuffer.hasRemaining()){
byte[] b = new byte[readBuffer.remaining()];
readBuffer.get(b);
blobWriter.write(b);
}
readBuffer.rewind();
processData(readBuffer); //<-- Further processing
...
}
The processData
method works fine when reading from a live stream of the market. For example, maybe processData reads a list of currencies and prints them, and the output is,
`EUR.USD.SPOT, EUR.AUD.SPOT, ..<thousands more>.. AUD.CAD.SPOT`
However, if I instead try to play back the captured bytestream (ie. Read in the contents of the file that was just previously created), on occasion, a corrupt symbol appears,
`EUR.USD.SPOT, EUR.AUD.SPOT, ..<thousands more>.. AUD.C@#$@##X`
Looking at the file in notepad++, indeed I find incorrect bytes (blue = correct symbols, red = malformed).
Subsequently, when the application points to the bytefile reader (instead of live market), the app fails at exactly these lines, throwing errors like Invalid symbol: EUR.-XD@#O@#$
.
For what it's worth, this is how I playback the file by reading it from disk and streaming to socket:
class FilePlayer implements runnable (Socket clientSocket) {
clientWriter= clientSocket.getOutputStream();
blobReader = new FileInputStream(blobFileName);
byte[] dataArray = new byte[1024]; //<-- Store 1024 bytes data at a time
...
}
public void run() {
while(true){
blobReader.read(dataArray); //<-- Read 1024 bytes of data from disk
clientWriter.write(dataArray); //<-- Write 1024 bytes of data to socket
}
}
Note, I recently opened a related thread similar thread, but that was in regard to FileChannels
, which were actually not the culprit. Figured that discussion had deviated enough to warrant a fresh post.