Why BufferedOutputStream doesn't output data? - java

I try to create my own class to output system out stream to console and to the file at the same time using BufferedStream. But data doesn't appear from the BufferedOutputStream. How should I fix this problem?
package com.library.stream;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class DoubleEndedStream {
InputStream theInput;
OutputStream theOutput;
public static void main(String[] args) throws IOException, FileNotFoundException {
DoubleEndedStream sr = new DoubleEndedStream(System.in, System.out);
sr.doublingTheStream();
}
public DoubleEndedStream(InputStream in, OutputStream out) {
theInput = in;
theOutput = out;
}
public void doublingTheStream() throws IOException, FileNotFoundException {
try {
FileOutputStream fos = new FileOutputStream("C:\\log.txt");
BufferedOutputStream bout1 = new BufferedOutputStream(fos);
BufferedOutputStream bout2 = new BufferedOutputStream(theOutput);
try {
while (true) {
int datum = theInput.read();
if (datum == -1) break;
bout1.write(datum);
bout2.write(datum);
}
bout1.flush();
bout2.flush();
} catch (IOException e) {
System.err.println("Couldn't read from System.in!");
}
bout1.close();
bout2.close();
fos.close();
} catch (FileNotFoundException e) {
System.err.println("Couldn't find log.txt");
}
}
}

Since theInput is System.in, as long as you don't close it, (ctrl-d in unix), it will not return -1, but hang and wait for input. Since you perform flush() only when received -1, you never get to this point. Try flushing after the write() instead.

Related

JUnit testing of OutputStream

I am trying to write a test for the writeMessage() method. But I have no idea how to start, since I need to test an OutputStream. This should be something like a small chat. It should read a message from console, write it to the text file and than print all messages that have been written to the file.
This is for a university project.
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
public class ChatIntImplement implements ChatI {
public static String readMessage() throws IOException, NullPointerException{
InputStream is = System.in;
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = null;
try {
message = br.readLine();
}catch(IOException ex) {
System.err.println("couldn't write data (fatal)");
System.exit(0);
}
return message;
}
public static void messageToFile(String message) throws IOException {
try {
String filename = "savedMessage.txt";
OutputStream os = new FileOutputStream(filename, true);
PrintStream ps = new PrintStream(os);
ps.println(message);
}catch (FileNotFoundException ex) {
System.err.println("couldn't open file - fatal");
System.exit(0);
}
}
public static void showMessages() {
InputStream is = null;
try {
is = new FileInputStream("savedMessage.txt");
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message;
while((message = br.readLine())!= null) {
System.out.println(message);
}
}catch(FileNotFoundException ex) {
System.err.println("couln't open file -fatal");
System.exit(0);
}catch(IOException e) {
System.err.println("couldn't read data (fatal)");
System.exit(0);
}
}
#Override
public void writeMessage(String message){
try {
messageToFile(message);
showMessages();
}catch (IOException e) {
System.err.println("couldn't write data (fatal");
System.exit(0);
}
}
#Override
public void exit() {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
ChatIntImplement chat = new ChatIntImplement();
try {
String message = readMessage();
chat.writeMessage(message);
}catch (IOException e) {
System.err.println("couldn't write data (fatal");
System.exit(0);
}catch (NullPointerException npe) {
System.err.println("Du hast nichts eingegeben");
System.exit(0);
}
}
}
I think the problem you are having getting started is because of how you have structured your class. All of your methods are static, and each method's dependencies, such as the various input and output streams you are using, are created as needed inside each method. For instance, in your messageToFile(...) method:
OutputStream os = new FileOutputStream(filename, true);
A much better approach to your project would be design your class using a traditional object-oriented class design that makes use of a pattern called Dependency Injection
The idea here is that your class that implements your ChatI interface would use member-variables for your input and output streams and the other objects, which would be initialized in the constructor for the class. Then you could control, and most importantly, get access to those streams from within your unit tests - something like this perhaps:
#Test
public void givenAMessageString_When() {
String expectedInput="expectedString";
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ChatIntImplement chat = new ChatIntImplement(baos);
...
chat.writeMessage(expectedInput);
string output = new String(baos.toByteArray());
assertThat(output).equals(expectedInput);
}

about closing BufferedOutputStream

I'm trying to develop a simple Java file transfer application using TCP.
My current server code is as follows:
package tcp.ftp;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class FTPServer {
public static void main(String[] args) {
new FTPServer().go();
}
void go() {
try {
ServerSocket server = new ServerSocket(2015);
System.out.println("server is running ....!");
while (true) {
Socket socket = server.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String file = reader.readLine();
System.out.println("file to be downloaded is : " + file);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
while (true) {
int octet = bis.read();
if (octet == -1) {
break;
}
bos.write(octet);
}
bos.flush();
//bos.close();
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
Using my current server code above, the downlloding does not work as expected. the above code sends part of the file to the client , not the entire file. Note that I used the flush method to flush the buffer. but when I replace the flush () method by the close () method, the file is fully sent to the client whithout any loss. Could anyone please explain this behavior!
UPDATE: Here is the code of my client:
package tcp.ftp;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
/**
*
* #author aaa
*/
public class FTPClient {
public static void main(String[] args) {
String file = "JasperReports-Ultimate-Guide-3.pdf";
try {
InetAddress address = InetAddress.getLocalHost();
Socket socket = new Socket(address, 2015);
System.out.println("connection successfully established ....!");
PrintWriter pw = new PrintWriter(socket.getOutputStream());
pw.println(file);
pw.flush();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy" + file));
while (true) {
int octet = bis.read();
if (octet == -1) {
break;
}
bos.write(octet);
}
bos.flush();
System.out.println("file download is complete ...!");
} catch (UnknownHostException ex) {
System.out.println(ex.getMessage());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
Another behavior without the use of Socket. take the following code that copy a file from a source to a destination:
public class CopieFile {
static void fastCopy(String source, String destination) {
try {
FileInputStream fis = new FileInputStream(source);
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(destination);
BufferedOutputStream bos = new BufferedOutputStream(fos);
while (true) {
int octet = bis.read();
if (octet == -1) {
break;
}
bos.write(octet);
}
bos.flush();
} catch (FileNotFoundException ex) {
System.out.println(ex.getMessage());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
public static void main(String[] args) throws IOException {
String source = "...";
String destination = "...";
fastCopy(source, destination);
}// end main
}// end class
the above code to copy a file from one location to another without any loss. Note well that I did not close the stream.
If you never close the stream the client wil never get end of stream so it will never exit the read loop.
In any case the stream and the socket are about to go out of scope, so if you don't close them you have a resource leak.

How to use IO Scanner/System.out copying video and photos?

I use io scanner / System.out to copy text files. I tried using the same technique to copy pdf, video and image files. The result was that the files were copied, but they were corrupt (cannot open them). Also, the file size does not equal the original file size.
code
import java.awt.Desktop;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Scanner;
public class ScannerTest {
public static void main(String[] args) throws IOException {
PrintStream out =System.out;
long start = System.currentTimeMillis();
copyFile(new File("H:\\a.pdf"), new File("H:\\b.pdf"));// 2 file input, output
System.setOut(out);
System.out.println(System.currentTimeMillis()-start);
}
static String text=null;
public static void copyFile(File input,File output) throws IOException{
//Scanner read file
Scanner in= new Scanner(new FileInputStream(input));
StringBuilder builder =new StringBuilder();
try {
while(in.hasNextLine()){
text=in.nextLine();
builder.append(text);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
in.close();
}
//System.out
try {
OutputStream outputStream = new FileOutputStream(output);
PrintStream printStream = new PrintStream(outputStream);
System.setOut(printStream);
System.out.println(new String(builder));
Desktop.getDesktop().open(output);
} catch (Exception e) {
e.printStackTrace();
}
}
}
p/s: Not use IO other.(ex: BufferedInput/OutputStream)
There are two problems (at least):
you use nextLine() which will read up to the next "\r\n"', '\n', '\r', '\u2028', '\u2029' or '\u0085' and discard what ever it found as line separator (one or two characters). As you are not even using append(text).append('\n') I doubt that this will correctly copy multi-line text, let alone binary files where each of the possible line-terminators may have a different meaning.
you use Scanner and StringBuilder which are not safe for binary data. As the Documentation on new Scanner(java.io.InputStream) states:
Bytes from the stream are converted into characters using the underlying platform's default charset.
If any byte-sequence in you input file is not valid as e.g. UTF-8 (which is a common default charset) it is silently replaced by a generic 'could not read input'-character. For text-files this can mean, that a 'ä' is converted to '�', for binary files this can render the whole file unusable.
If you want to copy arbitrary (possibly binary) files I would recommend not taking any chances and stick to byte[] APIs. You could however also use a charset which is known to accept all byte-sequences unchanged like ISO-8859-1 when creating Scanner and PrintStream; you would than still need to refrain from using line-APIs that suppress the found line-separator.
This should do the trick:
import java.awt.Desktop;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
/**
* Created for http://stackoverflow.com/a/25351502/1266906
*/
public class CopyFile {
public static void main(String[] args) {
long start = System.currentTimeMillis();
copyFile(new File("H:\\a.pdf"), new File("H:\\b.pdf"));// 2 file input, output
System.out.println(System.currentTimeMillis() - start);
}
public static void copyFile(File input, File output) {
try {
try (FileInputStream inputStream = new FileInputStream(input);
OutputStream outputStream = new FileOutputStream(output)) {
byte[] buffer = new byte[4096];
do {
int readBytes = inputStream.read(buffer);
if (readBytes < 1) {
// end of file
break;
} else {
outputStream.write(buffer, 0, readBytes);
}
} while (true);
}
// Open result
Desktop.getDesktop().open(output);
} catch (Exception e) {
e.printStackTrace();
}
}
}
pre Java 7 you need to use try-finally:
public static void copyFile(File input, File output) {
try {
FileInputStream inputStream = new FileInputStream(input);
try {
OutputStream outputStream = new FileOutputStream(output);
try {
byte[] buffer = new byte[4096];
do {
int readBytes = inputStream.read(buffer);
if (readBytes < 1) {
// end of file
break;
} else {
outputStream.write(buffer, 0, readBytes);
}
} while (true);
} finally {
outputStream.close();
}
} finally {
inputStream.close();
}
// Open result
Desktop.getDesktop().open(output);
} catch (Exception e) {
e.printStackTrace();
}
}

Send file over socket (with threading on server-side) - not working

I have a Client-Server programm. The Client-programm sends a file to the server and the server receives the file. my problem is, that the file is not really receiving on the server...I't creates a file.txt in the server-directory, but it is empty...(yes i'm sure that ne file.txt in the client-directory is not empty ;) )
I think the problem is the while-loop in Client.java, because it is never embarrassed....
For the future i implements now on the server side one thread per receiving file.
The client-programm:
package controller;
public class Main {
public static void main(String[] args) {
new Controller();
}
}
-
package controller;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Controller {
public Controller() {
try {
sendFileToServer();
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendFileToServer() throws UnknownHostException, IOException {
Socket socket = null;
String host = "localhost";
socket = new Socket(host, 5555);
String filename = "file.txt";
File file = new File(filename);
OutputStream outText = socket.getOutputStream();
PrintStream outTextP = new PrintStream(outText);
outTextP.println(filename);
long filesize = file.length();
byte[] bytes = new byte[(int) filesize];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
int count;
System.out.println("Start sending file...");
while ((count = bis.read(bytes)) > 0) {
System.out.println("count: " + count);
out.write(bytes, 0, count);
}
System.out.println("Finish!");
out.flush();
out.close();
fis.close();
bis.close();
socket.close();
}
}
-
The server-programm:
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
new Server();
}
}
-
public class Server {
private ServerSocket serverSocket;
public Server() {
try {
serverSocket = new ServerSocket(5555);
waitForClient();
} catch (IOException e) {
e.printStackTrace();
}
}
private void waitForClient() {
Socket socket = null;
try {
while(true) {
socket = serverSocket.accept();
Thread thread = new Thread(new Client(socket));
thread.start();
}
} catch (IOException ex) {
System.out.println("serverSocket.accept() failed!");
}
}
}
-
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
public class Client implements Runnable{
private Socket socket;
public Client(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
receiveFile();
}
private void receiveFile() {
try {
InputStream is = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
int bufferSize = 0;
InputStream outText = socket.getInputStream();
// Get filename
InputStreamReader outTextI = new InputStreamReader(outText);
BufferedReader inTextB = new BufferedReader(outTextI);
String dateiname = inTextB.readLine();
System.out.println("Dateiname: " + dateiname);
try {
is = socket.getInputStream();
bufferSize = socket.getReceiveBufferSize();
System.out.println("Buffer size: " + bufferSize);
} catch (IOException ex) {
System.out.println("Can't get socket input stream. ");
}
try {
fos = new FileOutputStream(dateiname);
bos = new BufferedOutputStream(fos);
} catch (FileNotFoundException ex) {
System.out.println("File not found.");
}
byte[] bytes = new byte[bufferSize];
int count;
while ((count = is.read(bytes)) > 0) {
bos.write(bytes, 0, count);
System.out.println("This is never shown!!!"); // In this while-loop the file is normally receiving and written to the directory. But this loop is never embarrassed...
}
bos.flush();
bos.close();
is.close();
socket.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
When you do these kind of transfers you have to keep in mind that there is a difference between a socket's close and shutdown, in your code you close the socket in the client.
So lets see what happens : you fill in the buffers then you tell the socket to close which will discard the operation you just asked for.
When you shutdown you tell the socket "I won't send more data but send what's left to be sent and shut down" so what you need to do is to shut down the socket before you close it so the data will arrive.
So instead of this
out.flush();
out.close();
fis.close();
bis.close();
socket.close();
Try it with this
out.flush();
socket.shutdownInput(); // since you only send you may not need to call this
socket.shutdownOutput(); // with this you ensure that the data you "buffered" is sent
socket.close();
Generally if you want a graceful close, you should do it like this in all cases even for the server, so what you did is usually okay if there is an error and you just close the connection since you cant recover from an error.

Socket read() doesn't block after second call on it

This is my Socket test program.
My problem is that when I execute the code below. After I call read() on Socket InputStream for first time, it block as expected.
But when loop go back to read() again, it never blocks on read() again? Thus it ends up with a tight and endless loop.
What should I do if I want to use separate thread to get server response? Is there any design pattern for this requirements?
package test.socket;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class TestMario {
private InputStream in;
private OutputStream out;
public static void main(String[] args) throws Exception {
new TestMario().go();
}
public TestMario() {
try {
Socket echoSocket = new Socket("xxx.xxx.xxx.xxx", 1234);
in = echoSocket.getInputStream();
out = echoSocket.getOutputStream();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void go() throws UnknownHostException, IOException {
Thread writer = new Thread(new Runnable() {
public void run() {
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
PrintWriter writer = new PrintWriter(out);
String userInput;
try {
System.out.print("input your command:");
while ((userInput = stdIn.readLine()) != null) {
System.out.println("you type:" + userInput);
writer.print(userInput);
writer.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
Thread reader = new Thread(new Runnable() {
StringBuffer sb = new StringBuffer();
public void run() {
while (true) {
System.out.println("waiting for server response...");
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] content = new byte[512];
int bytesRead = -1;
while((bytesRead = in.read(content)) != -1) { // read() doesn't block anymore after first read
baos.write(content, 0, bytesRead);
} // while
System.out.println("got:" + new String(baos.toByteArray()));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
});
writer.start();
reader.start();
System.out.println();
}
}
This means that it either returns -1 or throws IOException. You implemented 2 loops: the internal loop verifies that value returned by read and exits if value is -1. This is fine. However the outer loop while(true) makes you to enter the read again and again, so it is not blocked anymore because the end of stream is achieved.
EDIT: credits to #assylias that wrote comment that hints this.

Categories