I have a DataOutputStream I would like to copy into a string. I've found a lot of tutorials on converting DataOutputStreams by setting it to a new ByteArrayOutputStream, but I just want to read the string it sends when it flushes, and my DataOutputStream is already assigned to an output stream though a socket.
output.writeUTF(input.readLine());
output.flush();
If the context is helpful, I'm trying to read the output stream of a server and compare it to a string.
the flush method will flush, i.e. force write, anything buffered, but not yet written.
In the code below, try putting a breakpoint on the second call to writeUTF - if you navigate to your file system you should see the created file, and it will contain "some string". If you put the break point on flush, you can verify that the content has already been written to file.
public static void test() throws IOException {
File file = new File("/Users/Hervian/tmp/fileWithstrings.txt");
DataOutputStream dos = null;
try {
dos = new DataOutputStream(new FileOutputStream(file));
dos.writeUTF("some string");
dos.writeUTF("some other string");
dos.flush();//Flushes this data output stream. This forces any buffered output bytes to be written out to the stream.
} finally {
if (dos!=null) dos.close();
}
}
As such, you cannot extract the data from the DataOutputStream object, but in the example above we off course have those strings in the write calls.
Related
I need to store an error message in a string after the error has occurred. I am unable to use the try and catch blocks as the error will appear after the initial code is run.
Before I was using the code below to store the error message in a file when it appeared:
PrintStream printS = new PrintStream("file.txt");
System.setErr(pst);
However I want to store it and a string and send this string else where after the error occured. I have tried already using a byte array output stream:
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
PrintStream printS = new PrintStream(byteArray);
System.setErr(pst);
String tester = byteArray.toString(StandardCharsets.UTF_8);
But when I try to print the string it is empty and does not contain the error. Does anyone know how I can run code after a error has occurred, so I can send this error message elsewhere?
Java just runs code on the spot, you're not defining triggers for the future. You are creating a new empty byte array output stream, setting it up as 'target' for any System.err calls later, and then immediately turning it into a string. It's still blank at this point, of course.
What you want is quite complicated - you'd have to write a custom PrintStream that saves anything sent to it, until it 'sees' a newline and then acts. Something like:
OutputStream myCustomReportingStream = new OutputStream() {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
#Override public void write(int b) {
if (b == '\r') continue;
if (b == '\n') {
process(new String(buffer.getBytes(), StandardCharsets.UTF_8));
buffer.reset();
} else {
buffer.write(b);
}
}
private void process(String message) {
// YOUR CODE HERE
}
};
System.setErr(new PrintStream(myCustomreportingStream, true, StandardCharsets.UTF_8));
A bunch of things are happening here:
We're defining a custom OutputStream which buffers everything sent to it, until it sees \n (which is "newline" in ASCII, UTF-8, and many other encodings), at which point it turns the buffer into a string, sends that string to the process method, and clears out the buffer. It also ignores \r to deal with \r\n which is windows-style newlines.
We then use that OutputStream as basis for a new PrintStream, and then set up syserr to use this printstream.
This code does not deal with anything that sends data to System.err but doesn't send a newline symbol.
Anytime anybody anywhere runs System.err.println, your process() method will be run.
I'm trying to make a simple transfer of a text .txt file from client to server, and no matter how much I think I know, and understand what I'm doing, and what exactly happening, I always get it wrong. I can really use some help here please.
So, this is the code, two function that transfer a .txt file from one to another:
Client side:
private void sendFileToServer(String file_name) throws IOException {
File file=new File(file_name);
int file_size=(int)file.length();
byte[] bytes=new byte[file_size];
FileInputStream os=null;
try {
os = new FileInputStream(file);
} catch (FileNotFoundException e) {
System.out.println("The file "+file+" wasn't found");
return;
}
BufferedInputStream bos=new BufferedInputStream(os);
bos.read(bytes);
output.write(bytes,0,bytes.length);
/* 'output' is a PrintStream object, that holds the output stream
* for the client's socket, meaning:
* output=new PrintStream(client_socket.getOutputStream()); */
output.flush();
bos.close();
}
this will buffer everything into BufferedInputStream, will copy it to bytes and will then send it to the other side - the server.
Server side:
public static String receiveFileFromClient(Client client) throws IOException {
int buffer_size=client.getSocket().getReceiveBufferSize();
byte[] bytes=new byte[buffer_size];
FileOutputStream fos=new FileOutputStream("transfered_file.txt");
BufferedOutputStream bos=new BufferedOutputStream(fos);
DataInputStream in=client.getInputStream();
int count;
System.out.println("this will be printed out");
while ((count=in.read(bytes))>0) { // execution is blocked here!
bos.write(bytes, 0, count);
}
System.out.println("this will not be printed");
bos.flush();
bos.close();
return "transfered_file.txt";
}
My intention here is to keep reading bytes from the client (the while loop), until the other side (the client) have no more bytes to send, and this is where in.read(bytes) should return 0 and the loop should break, but this is never happens, it just get blocked, even though all the bytes from the client's input-stream were successfully transferred!
Why doesn't the loop breaks?
From Javadoc:
If no byte is available because the stream is at end of file, the
value -1 is returned
doesn't the last byte is considered "end of file"? I made sure that the function sendFileToServer properly writes the entire file to the output instance (PrintStream object) and returns.
Any help would be appreciated.
As i understand it, the read() method will block until either it read[bytes] OR the socket is closed. So there is nothing for the read() what would indicate that it should stop reading, because it does not "understand" the file, its just some data.
A solution...
You could determine the number of bytes the client will send (on the client side) and then send the NUMBER over to the server. Now the server can process this number and knows how many bytes to read before the file is complete. So you can break the loop (or even don't use a loop) when the transfer is completed.
You could also process the data the server receives, and let the client send some "flag" after the file is complete, so the server knows when it is done. But this is more difficult, because you have to find something, that is not contained in the file-byte data
read() method will block for further input if you dont close the stream. So eather close the stream, or remove the loop and only read the number of bytes, you receive from the client
i want to write a string to a serial port, but serial port write method allows only byte array to write in it...so how can i send whole string to a port..here is my code...
serialPort.setSerialPortParams(300,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
OutputStream mOutputToPort = serialPort.getOutputStream();
String mValue = "ABCDEFG";
System.out.println("beginning to Write . \r\n");
mOutputToPort.write(mValue.getBytes());
System.out.println("AT Command Written to Port. \r\n");
mOutputToPort.flush();
i dont want to send it one by one char..i want whole at a time... thnxx in advance
Your code works (it does write the whole string at once), but it is not nice. If this is what you intend to do, the "clean" way to do it is:
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(mOutputToPort));
bw.write(mValue);
// probably "write" some more here to the buffer
bw.flush(); // now ensure accumulated data is actually written
If you are only writing one string and not more you might as well use an OutputStreamWriter directly and not use a buffer:
OutputStreamWriter osw = new OutputStreamWriter(mOutputToPort);
osw.write(mValue, 0, mValue.length());
osw.flush();
(In Java, Writers deal with writing characters to streams instead of bytes.)
If you want to ensure that no buffering occurs (and I doubt there is any reason for it, it will only increase system call overhead since the serial port will buffer the data anyway and send it out slower than your code delivers it), 123456789 provided a suitable answer. You should be careful with calling getBytes() though, as this will use the system's default character encoding (usually UTF-8 or ISO-8859-1, both suitable for writing pure ASCII) to convert from characters to bytes. If you want a particular encoding then specify it in the call to getBytes(), e.g.
try {
byte[] bytes = someString.getBytes("US-ASCII");
for (int i=0; i<bytes.length; i++)
mOutputToPort.write(bytes[i]); }
catch (UnsupportedEncodingException e) {} // well, this one is always supported
Try to use getBytes() method which returns byte array.
OutputStream mOutputToPort = serialPort.getOutputStream();
String mValue = "ABCDEFG";
System.out.println("beginning to Write . \r\n");
Byte[] data = mValue.getBytes();
for(int i=0;i<data.length;i++){
mOutputToPort.write(data[i]);}
System.out.println("AT Command Written to Port. \r\n");
mOutputToPort.flush();
I'm pretty new to JAVA, so I do not really see what I am doing wrong within the following method:
public void writeWNDFile(){
String strFilePath = "C:/Users/fperrone/Desktop/ddd.txt";
try
{
//create FileOutputStream object
FileOutputStream fos = new FileOutputStream(strFilePath);
DataOutputStream dos = new DataOutputStream(fos);
dos.writeDouble(12);
dos.close();
}
catch (IOException e)
{
System.out.println("IOException : " + e);
}
}
The file is actually generated, but I don't get 12 as printed and expected result, but #(, which probably is the ASCII representation.
May you shed some light?
EDIT
Does eventually exist a JAVA function behaving similarly to the MATLAB fwrite function? I actually wanna write a binary file. In MATLAB I am simply calling:
fwrite(filename, A, precision)
How could I achieve the same in JAVA?
DataOutputStream.writeDouble and other methods of DataOutputStream are designed to write numbers in binary format. If you want your data be saved in text format use FileWriter and its write(String) method. You can convert double to String with Double.toString(double).
from writeDouble java docs:
Converts the double argument to a long using the doubleToLongBits
method in class Double, and then writes that long value to the
underlying output stream as an 8-byte quantity, high byte first.
As DataOutputStream uses the binary format to write, hence you are seeing the same. But you need to worry if you are going to read the file again using DataInputStream and readDouble method. It should give you the right values.
//PrintWriter out = new PrintWriter(new BufferedWriter(
// new OuputStreamWriter(new FileOutputStream(strFilePath) /*, "UTF-8"*/)));
PrintWriter out = new PrintWriter(strFilePath /*, "UTF-8"*/);
out.println(12);
out.close();
Add the encoding, here UTF-8, when you want the application to write with the same encoding everywhere. Otherwise the default platform encoding is used.
PrintWriter's println adds a newline, print not.
I've got some trouble with sending a UTF8 string from a c socket to a java socket.
The following method works fine:
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF8"));
main.title = in.readLine();
but then I need a int java.io.InputStream.read(byte[] b, int offset, int length) method which does not exist for a BufferedReader. So then I tried to take a DataInputStream
DataInputStream in2 = new DataInputStream(socket.getInputStream());
but everything it reads is just rubbish.
Then I tried to use the readLine() method from DataInputStream but this doesn't give me the correct UTF8 string.
You see my dilemma. Can't I use two readers for one InputStream? Or can I convert the DataInputStream.readLine() result and convert it to UTF8?
Thanks,
Martin
We know from the design of the UTF-8 encoding that the only usage of the value 0x0A is the LINE FEED ('\n'). Therefore, you can read until you hit it:
/** Reads UTF-8 character data; lines are terminated with '\n' */
public static String readLine(InputStream in) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
while (true) {
int b = in.read();
if (b < 0) {
throw new IOException("Data truncated");
}
if (b == 0x0A) {
break;
}
buffer.write(b);
}
return new String(buffer.toByteArray(), "UTF-8");
}
I am making the assumption that your protocol uses \n as a line terminator. If it doesn't - well, it is generally useful to point out the constraints you're writing to.
Do NOT use BufferedReader and DataInputStream on the same InputStream!! I did that and spent days trying to figure out why my code broke. BufferedReader can read more than what you extract from it into its buffer, resulting in situation when the data I was supposed to read with the DataInputStream being "in the BufferedReader". This resulted in lost data which caused my program to "hang" waiting for it to arrive.
I believe that you should not mismatch the BufferedReader and DataInputStream here. DataInputStream has readLine() too, so use it.
And yet another comment. I am not sure it is a problem but avoid multiple calls of socket.getInputStream(). Do it once and then wrap it as you want using other streams and readers.
Am I understanding it correctly that you are sending both text and binary data on the same socket, in the same "conversation"? There should be no problem creating two readers for the same inputstream. The problem is knowing when (and how much) to read which reader. They will both consume (and advance) the underlying stream when you read from them, since you have mixed types of data. You could just read the stream as bytes and then convert the bytes explicitly in your code (new String(bytes, "UTF-8") etc). Or you could split your communication onto two different sockets.