I was practicing using byte streams in Java when I came across this code:
import java.io.*;
public class CopyBytes_practice {
public static void main(String args[]) throws IOException {
FileInputStream f=null;
FileOutputStream fo=null;
int c;
int d;
try {
f=new FileInputStream("a.png");
fo=new FileOutputStream("b.png");
c=f.read();
while(c != -1){
fo.write(c);
}
} finally {
if (f != null) {
f.close();
}
if (fo != null) {
fo.close();
}
}
}
I used a 35kb a.png file and a 0kb b.png file to execute the code, but the code ran forever - the size of b.png reached 905mb before I stopped the JVM manually.
I am confused, why is the end of file status not returned? Is it not supported in Binary files, or is something else wrong?
You missed something important
c=f.read(); // <-- Read in one byte ...
while(c != -1){
fo.write(c);
c=f.read(); // <--- Add this, to Read in the next byte (or -1)...
}
So you were infinitely looping, and writing the first byte from your source.
Yes, because it's an infinite loop, you need to tell the loop where to stop.In other words, the loop should keep reading until it reaches the end of the file.
while ((c= f.read()) != -1){
fo.write(c);
}
Related
At the following program, in case I remove the return statement from:
catch(FileNotFoundException e) {
System.out.println("File Not Found");
return;
It shows me an error inside the do while loop, that the local variable fin might not have been initialized. Can someone explain me why is this happening?
import java.io.*;
class Stock {
public static void main(String args[])
throws IOException {
int i;
FileInputStream fin;
try {
fin = new FileInputStream(args[0]);
} catch(FileNotFoundException e) {
System.out.println("File Not Found");
return;
}
// read characters until EOF is encountered
do {
i = fin.read();
if(i != -1) System.out.print((char) i);
} while(i != -1);
fin.close();
}
}
If you remove the return statement, you get:
public static void main(String args[])
throws IOException {
int i;
FileInputStream fin;
try {
fin = new FileInputStream(args[0]);
} catch(FileNotFoundException e) {
System.out.println("File Not Found");
}
// read characters until EOF is encountered
do {
i = fin.read();
if(i != -1) System.out.print((char) i);
} while(i != -1);
fin.close();
}
Now if FileInputStream throws an exception, it doesn't return a result, and fin doesn't get initialized. The catch block handles the exception and prints a message, but then the code continues, and the next thing it tries to execute is i = fin.read(). Since the compiler figures out that there's a possible way to get to this statement without initializing fin or assigning anything to it, it won't compile the program.
If you put the return back in, this can't happen, because the catch block will cause main to return, and you can't get to fin.read().
The exception could have been thrown in the call in the try block, so no value will have been assigned to the variable fin. Without the return statement, the subsequent use of the uninitialized fin variable causes the compiler to complain.
With the return statement, if the fin variable is never initialized, it is never used, either, so the compiler is okay with that.
Why compiler complain
- if your main() encounter the exceptions it will pass try catch block and never get the
chance to initialize fin variable
- Compiler knows that program may end up with throwing an exception which has high chance
in order to avoid any fruther issue it will not complie
I advise you to do this
- use try catch block with resources since Java 7 since Class `FileInputStream` is `closable`
- put everything in a good order
code:
try(FileInputStream fin =new FileInputStream(args[0]) ) {
while ((content = fin.read()) != -1) {
// convert to char and display it
System.out.print((char) content);
}
} catch(FileNotFoundException e) {
System.out.println("File Not Found");
return;
} ...
....
..
Source:
http://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html
http://tutorials.jenkov.com/java-exception-handling/try-with-resources.html
An exception could occur in new FileInputStream(args[0]);, which would cause fin to not have been initialized.
Try using a default value for fin:
fin = null;
Then later, check to make sure it is not null:
if (fin != null)
{
do {
i = fin.read();
if(i != -1) System.out.print((char) i);
} while(i != -1);
fin.close();
}
If an exception is encountered while instantiating the FileInputStream, then control moves to the catch block before a value is stored in the variable fin. Without the return statement in place the program would continue execution into the do/while loop, where a method (read) would be called on the uninitialized variable, resulting in an error.
Note: I understand that the console is for debugging and games should use GUI. This is for testing/experience
I'm writing a game that runs at 60fps. Every update, I check to see if the user has entered a String command. If so, it gets passed through, but if not, null is paas through, and the null is ignored.
Scanner is out of the question, since hasNext(), the method used to see if there is data to read, can potentially block and causes problems.
I've tried using BufferedReader.ready(). Not only did I have problems (never returned true), but I've read that it's not recommended for a few reasons.
BufferedReader.available() always returned 0, which in the documentation, it state's that InputStream.available() will always return 0 unless overriden. Here is my attempt:
class Game {
public static void main(String[] args) {
InputReader reader = new InputReader(System.in);
int timePerLoop = 1000/30;
Game game = new Game();
while(true) {
long start = System.nanoTime();
game.update(reader.next());
long end = System.nanoTime();
long sleepTime = timePerLoop + ((start - end) / 10000000);
if(sleepTime > 0)
try {
Thread.sleep(sleepTime);
}catch(InterruptedException e) {
e.printStackTrace();
}
else
Thread.yield();
}
}
public void update(String command) {
if(commands != null) {
//handle command
}
//update game
}
}
InputReader.java
public class InputReader {
private InputStream in;
public InputReader(InputStream stream) {
in = stream;
}
public String next() {
String input = null;
try {
while(in.available > 0) {
if(input == null)
input = "";
input += (char) in.read();
}
}catch(IOException e) {
e.printStackTrace();
}
return input;
}
}
InputStream by itself has the same problem as above. I'm not completely sure what type the object stored in System.in, but using available() yields the same results.
I've tried using the reader() from System.console(), but console() returns null. I've read into the subject, and I am not confused why. This is not the way to do it.
The goal is to check the stream to see if it contains data to read, so I can read the data knowing it won't block.
I do not want to use a separate Thread to handle user input, so please don't recommend or ask why.
The input has to be from the console. No new sockets are to be created in the process. I have read a few topics about it, but none of them clearly states a solution. Is this possible?
As you have said yourself, a custom GUI or an additional thread is the correct way to do this. However in absence of that, have you tried using readLine() for example: String inputR = System.console().readLine();
Some alterations to main():
Replace: InputReader reader = new InputReader(System.in); with:
Console c = System.console();
Replace: game.update(reader.next());
with: game.update(c.readLine());
Edit: This thread could also be helpful: Java: How to get input from System.console()
I want to read and handle a stream of String containing single OR multiple commands in one line.
I am currently using InputStream in = socket.getInputStream(); for my inputstream.
Also for handling the input a typical Thread:
public void run() {
String input = "";
try {
int data = 0;
while (!isInterrupted()) {
while ((data = in.read()) != -1 && !isInterrupted()) {
input += Integer.toHexString(data);
handleInput(input);
}
try {
sleep(500);
} catch (InterruptedException e) {
break;
}
}
socket.close();
return;
} catch (IOException e) {
main.log("Connection lost...");
main.log(e.toString());
main.stopBTCommunication();
main.startBTServer();
}
}
handleInput() is designed to handle any String given to it and response correctly. The problem with this implementation would be, that handleInput() is called with every byte read from in.read(). I know, that i could use BufferedReader.readLine(), but that would require every incomming command to have "\n" appended to it, which is NOT the case and can't be changed.
I know that
while (!isInterrupted()) {
while ((data = in.read()) != -1 && !isInterrupted()) {
is kind of nuisance, but basically it want the Thread to read until nothing new is read, then handle that input and then read again...
EDIT:
So basically, what i need is a non-blocking read().
EDIT2:
How can incoming commands and commandchains look like:
Select Command: "s"
ReadLine Command: "rlXX" whereby X is a Hex Digit
WriteLine Command: "wlXXSSSSSSSS" whereby X and S are Hex Digits
So a commandschain may look like one of the following:
"s"
"srlff" = "s" + "rlff"
"rlffwlbb2e2e2e2erlbb" = "s" + "rlff" + "wlbb2e2e2e2e" + "rlbb"
I don't think you really need a non-blocking read. You need a method that reads the stream byte by byte and translates it into commands as it goes.
Something like:
public void processStream(InputStream in) {
List<Command> commands = new ArrayList<Command>();
while((int c = in.getChar()) != -1 ) {
switch((char)c) {
case 's':
commands.add(new SelectCommand());
break;
case 'r':
commands.add(ReadCommand.buildFromStream(in));
break;
case 'w':
commands.add(WriteCommand.buildFromStream(in));
break;
case ';':
commandEngine.execute(commands);
break;
default:
throw new StreamParseError("unexpected character: " + c);
}
}
}
This assumes that SelectCommand, ReadCommand, WriteCommand are type-compatible with Command.
... with for example ReadCommand.buildFromStream being:
public static ReadCommand buildFromStream(InputStream in) {
if((char)in.read() != 'n') {
throw new StreamParseError("Expect 'l' after 'r'");
}
// bad error checking here - be less lazy in real life.
String hexNum = in.read() + in.read();
int num = Integer.parseInt(hexNum,16);
return new ReadCommand(num);
}
This is very primitive parsing, but it shows the principle. There are well established techniques for more advanced parsing, which you can read up on if you want to.
You could also use a Scanner. Most commonly, Scanner is used with delimiters, but it can also look for regex patterns.
Scanner scanner = new Scanner(stream);
String cmd = "";
while(cmd != "e") { // I made up an "end" command :)
cmd = scanner.findWithinHorizon("(s|rl..|wl.{8}|e)",12);
if(cmd == null) {
// end of input, or badly formed input
break;
}
handleCmd(cmd);
}
You can read in array of bytes like this
int bytesRead = 0;
byte[] buffer = new byte[1024]; // reads up to 1024 byte chunks
while((bytesRead = in.read(buffer)) != -1) {
for ( int i = 0; i < bytesRead; i++ ) {
input += Integer.toHexString(buffer[i]);
}
handleInput(input);
}
The above code calls is the same as your old code that "input" keeps growing and used over and over again to call handleInput(). No sure if this is your intention but it looks suspicious.
Note that you are reading data from a stream. This means that you will have to implement recovery of the commands' structure yourself, i.e. you must at least detect the beginning and end of a command in your own code.
This again leads to another problem: You have no guarantee about how your stream's data is split into "chunks" by the transport layer. You may receive one command plus half a command in one read(buffer) call and then the second half of the command plus some more data in the next read(buffer).
Therefore, what I recommend is that you keep reading data only until you detect the end of one message/command/whatever and then perform handling for only this single message, before reading more incoming data and repeating. Everything else (i.e. dealing with partially received messages) easily becomes messy.
EDIT - With this particular input/output, since you don't have a delimiter, Scanner may not be the way to go here, but if you've got a delimiter between commands, it would be a great option, so I'll keep the answer here in the hopes it might help someone in the future.
Since your example doesn't have a delimiter, I have to get a little bit hack-y to demonstrate scanner's awesomeness, but it should still work for the exact commands you've listed. It would not be a good choice if you expect the command vocabulary to change.
I'd really recommend the use of delimiters if at all possible. It makes life much easier.
I'd look at the Scanner class if I were you.
The Scanner can wrap your input stream, and then scan based on a regex or delimter to grab chunks of input. Then your handleInput() method can operate on chunks (whole commands) rather than individual bytes.
Here's a brief, standalone example:
package com.stackoverflow.q22199860;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import java.util.regex.Pattern;
public class ReadStream
{
public static void main(String[] args)
{
Pattern commandPattern = Pattern.compile("s|rl|wl");
String commands = "srlffwlbb2e2e2e2erlbb";
Charset utf8 = StandardCharsets.UTF_8;
try (
InputStream inputStream = new ByteArrayInputStream(commands.getBytes(utf8));
Scanner scanner = new Scanner(inputStream, utf8.name());
) {
scanner.useDelimiter(commandPattern);
while(scanner.hasNext()) {
String command = scanner.next();
if (command.isEmpty()){
//s
System.out.println("s" + command);
} else if (command.length() == 2) {
//rl
System.out.println("rl" + command);
} else if (command.length() == 10) {
//wl
System.out.println("wl" + command);
}
}
}
catch (IOException e)
{
System.err.println("Error Reading Stream");
}
}
}
The output from this is:
s
rlff
wlbb2e2e2e2e
rlbb
I am writing a small program to retrieve a large number of XML files. The program sort of works, but no matter which solution from stackoverflow I use, every XML file I save locally misses the end of the file. By "the end of the file" I mean approximately 5-10 lines of xml code. The files are of different length (~500-2500 lines) and the total length doesn't seem to have an effect on the size of the missing bit. Currently the code looks like this:
package plos;
import static org.apache.commons.io.FileUtils.copyURLToFile;
import java.io.File;
public class PlosXMLfetcher {
public PlosXMLfetcher(URL u,File f) {
try {
org.apache.commons.io.FileUtils.copyURLToFile(u, f);
} catch (IOException ex) {
Logger.getLogger(PlosXMLfetcher.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I have tried using BufferedInputStream and ReadableByteChannel as well. I have tried running it in threads, I have tried using read and readLine. Every solution gives me an incomplete XML file as return.
In some of my tests (I can't remember which, sorry), I got a socket connection reset error - but the above code executes without error messages.
I have manually downloaded some of the XML files as well, to check if they are actually complete on the remote server - which they are.
I'm guessing that somewhere along the way a BufferedWriter or BufferedOutputStream has not had flush() called on it.
Why not write your own copy function to rule out FileUtils.copyURLToFile(u, f)
public void copyURLToFile(u, f) {
InputStream in = u.openStream();
try {
FileOutputStream out = new FileOutputStream(f);
try {
byte[] buffer = new byte[1024];
int count;
while ((count = in.read(buffer) > 0) {
out.write(buffer, 0, count);
}
out.flush();
} finally {
out.close();
}
} finally {
in.close();
}
}
I have something akin to the following:
public class X extends Thread{
BufferedInputStream in = (BufferedInputStream) System.in;
public void run() {
while (true) {
try {
while (in.available() > 0) {
// interesting stuff here
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
... which largely works, however sometimes I'll start seeing the following in stderr (seems to repeat incessantly once it happens - I'm guessing the application eventually crashes once this starts occurring):
java.io.IOException: Illegal seek
at java.io.FileInputStream.available(Native Method)
at java.io.BufferedInputStream.available(BufferedInputStream.java:381)
at compactable.sqlpp.X.run(X.java:40)
... and I have no clue what causes this. Honestly stumped. Any ideas from the masses on how this could happen ?
Any / all useful suggestions gratefully received :-)
If the stream has been closed you can get an IOException calling available.
Also, available() does not tell you how much is left to read of the stream or if the stream is empty, it only tells how much you can read without blocking (basically waiting for more to be put into the stream). What you want is to read until your read returns -1.
int c;
while ( (c = in.read()) != -1 ) {
// do stuff
}
or
int readLength;
byte[] buffer = new byte[1024];
while ( (length = in.read(buffer) != -1) {
// do stuff with buffer, it now has bytes in buffer[0] to buffer[readLength-1]
}