How does this Java method work to read input string? - java

My Java class is creating a program in which a person thinks of a certain animal within a list of animals, and answers various yes/no questions (such as "Does your animal live on land?" or "Does you animal fly?" etc.) for the computer to determine what animal it is. Everyone in my class was issued a source code to begin working with, and one of the methods within it is obviously designed to read code and I'm not sure how it works exactly, but would like to know how it works to use it in my own programming projects. Any help to know exactly what it does would be greatly appreciated. Thanks!
public static String read()
{
byte[] buffer = new byte[10];
try
{
int numBytes = System.in.read(buffer);
}
catch(IOException e)
{
System.out.print("Error: " + e);
System.exit(1);
}
String str = new String(buffer);
int ball = 5;
return (str);
}

public static String read()
{
byte[] buffer = new byte[10];
Creates an array of ten bytes.
try
Begins a protected portion of code in which some error could happen (exception).
{
int numBytes = System.in.read(buffer);
Reads at most 10 bytes from input.
}
catch(IOException e)
{
In case reading request encounters a condition that makes your reading impossible, execute that block of code.
System.out.print("Error: " + e);
Prints a message.
System.exit(1);
Terminates the execution with indication that something goes wrong.
}
In case reading was ok (no error in try block), control flow ends here.
String str = new String(buffer);
Construct a String with what was read (at most 10 bytes).
int ball = 5;
Does nothing interesting here, except initializing a variable that is never used.
return (str);
Returns the constructed value (what was read on input as a String) to the caller of that method.
}

Related

SpotBugs - Method ignores results of InputStream.read()

I am having some problems debugging a code, I managed to debug all bugs but one:
Method ignores results of InputStream.read(), the debugger (SpotBugs) says the problem is on reader.read(buffer, 0, n) and advises me to check the return value otherwise the caller will not be able to correctly handle the case where fewer bytes were read than the caller requested.
char[] buffer = new char[n];
try{
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
reader.read(buffer,0,n);
reader.close();
}
catch(RuntimeException e) {
throw e;
}
catch(Exception e) {
System.out.println("Something went wrong");
}
for(int i=0;i<buffer.length;i++) {
int swap = i % 2;
if (Integer.toString(swap).equals(Integer.toString(1))) {
buffer[i] = ' ';
}
}
System.out.print(buffer);
How can I fix this bug?
read() when used with a buffer returns the actual number of the bytes read (or -1 for end of stream). It's possible that the buffer isn't filled completely with a single read (although small buffers are, since data is transferred in blocks), so you need to make sure (i.e. use a while loop) you've read the amount of bytes you intended to.
R. Castro gave you good explanation, but what's missing (in obvious words) is you are not checking how many bytes are being read from file. The number can be different than size of your buffer. That's what spotbug is trying to tell you. Your file can be longer or shorter than buffer size. You are not handling the case where file is longer than buffer size. And loop you have needs to be changed to whatever number of bytes are read than buffer.length

Try and catch method not working java

I have been trying to get my try/catch set up to work but it doesn't seem to run either the try section or the catch section and just returns the default value of the variable.
I had it working before and cant remember what it was that i changed because I haven't touched it for a while
i can include the data file if requested
Any ideas?
package firsttry;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.InputMismatchException;
import java.util.Scanner;
public class csv{
public double speed(int tool , int block){
double blockbreak = 0;
//Define file variable thing
//runs through file
try {
String filename = "data.csv";
File file = new File(filename);
Scanner inputStream = new Scanner(file);
//runs through each line as long as there is something next
while (inputStream.hasNext()){
String data = inputStream.next();//gets a whole line
String[] values = data.split(",");
if (values[1].equals(block)){
blockbreak = Double.parseDouble(values[tool + 2]);
System.out.println(blockbreak);
blockbreak = 4;
}
}
}catch (Exception e) {
System.out.println("ERROR");
blockbreak = 4;
}
return blockbreak;
}
public String name(int block){
String filename = "data.csv";
File file = new File(filename);
//runs through file
try {
Scanner inputStream = new Scanner(file);
//runs through each line as long as there is something next
while (inputStream.hasNext()){
String data = inputStream.next();//gets a whole line
String[] values = data.split(",");
if (values[1].equals(block)){
//int speed = Integer.parseInt(values[tool]);
String blockname = values[0];
return blockname;
}
}
} catch (FileNotFoundException e) {
}
return filename;
}
}
Don't have enough reputation to comment, so writing here.
You should modify your if condition in each function() written above,
if (values[1].equals(block)){
}
It will not give you an output you are expecting.
Comparing string with int is incorrect, for example
System.out.println("1".equals(1)); -> will print false
You are observing that the default value is being returned.
Does this mean that your function returns 0? (As initialized here? double blockbreak = 0;)
If that is the case, you should look into what happens in your loop.
This if statement looks dodgy.
if (values[1].equals(block))
What do you expect to happen?
Also, please post a line that matches the if statement and a line that doesn't, and the expected output from the function.
Possible reasons why you only get the default value:
data.csv is an empty file.
values[1].equals(block) returns false. (Which will always be the case since you're comparing a String to an int.)
catch (FileNotFoundException e) doesn't do anything, so you wouldn't know if the file was not found.
To elaborate on point 2, consider values[1].equals(String.valueOf(block))
Let me suggest some troubleshooting tips.
Write a unit test so you can easily run this repeatedly.
Put a System.out.println into the code in a few places to see which places it hits and when (On small problems this is often easier than debugging if you don't typically debug, I often have it print out a letter at the beginning of any code that comes after a decision point like if, loop and try/catch constructs.)
Print out the value of each line as you read it.
Print the value of blockbreak
I would guess your loop or the if statement aren't executing. Printing some values will tell you this quickly.
Also, if you truly intend Blockbreak to be assigned a value, try NOT assigning a default value of 0 in the beginning. This will stop you from compiling until you have assigned a value in every possible program flow path--a very handy feature (May not help in your case because of the way your while loop is structured, but it's a useful habit not to assign initial values until you need to in Java).

java.lang.NumberFormatException: For input string: "" when using "2" or "5"

I read in a menu choice and typing in any number but 2 & 5 work.
String choice = promptUser(choicePrompt);
try {
outputInfo(String.format("choice=...%s...",choice));
int c = Integer.parseInt(choice);
/* process it */
}catch (NumberFormatException e) {
outputInfo(String.format("choice=%s",choice));
outputInfo(e.toString());
}
public static void outputInfo(String msg)
{
System.out.printf("\t%s\n",msg);
}
Good output:
Enter Option: 1
choice=...1...
Bad Output:
Enter Option: 2
choice=...2...
choice=2
java.lang.NumberFormatException: For input string: ""
Update:
I've hard-coded "2" and it still fails!:
String choice = promptUser(choicePrompt);
try {
choice="2";
outputInfo(String.format("choice=...%s...",choice));
int c = Integer.parseInt(choice);
/* process it */
}catch (NumberFormatException e) {
outputInfo(String.format("choice=%s",choice));
outputInfo(e.toString());
}
Hard-coding "5" also fails but "1" works!!!
Any ideas gratefully received.
Simon
If I assume your promptUser() method to be something like:
static String promptUser() {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try {
return reader.readLine();
}
catch(Exception ex) {
return null;
}
}
(without the parameter) then the program behaves as expected - certainly there's nothing in that code that treats 2 or 5 differently. If you're getting an empty string then are you sure your prompt user method is working correctly?
Either way, the code you've posted here is essentially correct. I would imagine there's something else wrong in your more fully complete program that doesn't manifest itself when you've reduced it down here; perhaps you're running into a case where a local variable is hiding a field for example and you're not using the value you think you are (but at this point, I'm just guessing.)
updated
Seems the promptUser method is returning an empty String "". check if choice is empty before calling
ParseInt method
Also you can add trim() to eliminate spaces before and after the input
if(choice!=null && !"".equals(choice))
int c = Integer.parseInt(choice.trim());
printStackTrace() is your friend.
Turns out the number format exception was further down (in the 'process it' code) and was not being caught down there.
It was data driven so didn't happen on other machines.
Thanks to every one for your support.
Simon

Why would someone structure a while loop like this?

I'm reading a book on Java, and we're on reading from a channel into a ByteBuffer. I found the way the author was structuring the while loop odd:
try (FileChannel inCh = (FileChannel) Files.newByteChannel(file)) {
ByteBuffer lengthBuf = ByteBuffer.allocate(8);
int strLength = 0;
ByteBuffer[] buffers = { null, ByteBuffer.allocate(8) };
while(true) {
if(inCh.read(lengthBuf) == -1)
break;
lengthBuf.flip();
strLength = (int)lengthBuf.getDouble();
buffers[0] = ByteBuffer.allocate(2*strLength);
if(inCh.read(buffers) == -1) {
System.err.println("EOF found reading ht eprime string.");
break;
}
System.out.printf("String length: %3s String: %-12s Binary Value: %3d%n", strLength,
((ByteBuffer) (buffers[0].flip())).asCharBuffer().toString(),
((ByteBuffer)buffers[1].flip()).getLong());
lengthBuf.clear();
buffers[1].clear();
}
System.out.println("\nEOF reached.");
} catch (IOException e) {
I tried it like this:
while(inCh.read(lengthBuf) != -1) {
and it works the same. Would there be a practical or code clarity reason the author would write it like he did?
It is clear that your version of the loop is semantically identical. However, that's not the only thing to consider.
Notice that further down the while loop there is a second condition that breaks out of the loop. I suspect that this is what has motivated the author to use while (true).
By writing it as while (true) you alert the reader to the fact that there must be one or more breaks inside the while. The reader is going to have to look inside the loop for breaks, and will hopefully find them both.
Written your way, the casual reader might scan the top of the code and assume that the while condition was the only way for the loop to terminate.
Another point to consider is that of symmetry, or balance. As written by the original author, the loop terminations are all of the same form. Namely breaks from within the loop. Your version feels asymmetrical. One termination point in the while test, and a further termination point, of a different nature, inside the loop.
The author has two exit points, one of which prints out an error before exiting the loop. Just makes the code a little more verbose in that case. It can be written in a number of different ways of course.

How to create multiple files, generating a random name for each file

What I'm trying to do is create lots of random files but I'm just completely lost. The code below just doesn't work, I'm wondering why it doesn't work and what can i do to fix it.
import java.io.*;
import java.util.*;
public class main {
public static void main(String arg[]){
Random rn = new Random();
int randn = 1+rn.nextInt(999999990);
String I_S = Integer.toString(randn);
Formatter file;
try{
for(int i = 0; i < 9999999; i++){
file = new Formatter("%s.txt", I_S);
}
}
catch(Exception ex){
System.err.println("Error");
}
}
}
By just generating random numbers, you may end up creating / overwriting the same file multiple times. To have an absolutely unique set, do something like this:
final int MAX = 9999999;
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < MAX; i++) {
list.add(i);
}
Collections.shuffle(list);
for (int i = 0; i < MAX; i++) {
// create files here
}
How to create multiple files, generating a random name for each file.
You probably want to have a look at File.createTempFile.
Looking at your code, you probably want something like
Random rn = new Random();
String file;
for (int i = 0; i < 100; i++)
file = String.format("%i.txt", 1+rn.nextInt(999999990));
I'm not sure exactly what you expect this code to achieve, but right now it effectively does nothing.
You're looping many, many times creating an instance of Formatter each time. This is not a file; instead, it's a class that knows how to replace tokens in strings to create other strings.
I think you're confused by the description of the constructor you're calling and the purpose of the class as a whole. The constructor takes as its first argument the name of the file to use for output - in your case, this will always be %s.txt. The second argument is the name of a supported charset to use for encoding the String to the file.
This code will always fail because:
Your I_S variable, e.g., "56437890" is not a valid encoding (whereas "UTF-8" would be). Hence the constructor will probably throw an exception when trying to work out the encoding scheme.
Even if the charset was miraculously right, you're still trying to write to the same file (%s.txt) every time, so you wouldn't get the desired multi-file behaviour.
This string may not even be a valid filename, depending on your OS, and so if the Formatter tries to create the file it will throw an exception.
If both arguments miraculously work out, you're still not actually doing anything with the formatter, so it doesn't have anything to write out to the file which thus may not be created.
Finally, you're not updating your random variable (I_S) in the loop - it gets set once, and then maintains the same value forever. So even if all the above problems weren't issues, you'd still create the same (single) randomly-named file over and over and over again.
And as I noted in the comments, when it fails, you're catching and swallowing the exception so you have absolutely no way of knowing what went wrong.
Fundamentally I think you're confused about the purpose of the Formatter class, and since I don't know what you're trying to achieve (should the files be empty? Have specific text in?) I can't suggest something which definitely works. However, if you just want to create empty files, try something like this inside your loop:
String filename = "%s.txt".format(I_S);
File file = new File(filename);
file.createNewFile();
// Add some logic to update the random variable here!
As a final point, adarshr's answer is entirely right that you stand a nontrivial chance of repeating random numbers, so you won't get exactly as many files as you expect. The answer goes on to describe a good way to avoid this, and it's worth following.
You may want to look into writing something more like this:
void Write()
{
try {
for(int i = 0; i < MAX_FILES; i++) {
FileWriter outFile = new FileWriter("C:\File" + i.toString() + ".txt");
PrintWriter out = new PrintWriter(outFile);
// Write text to file
out.println("This is line 1");
out.println("This is line 2");
out.print("This is line3 part 1, ");
out.println("this is line 3 part 2");
out.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
// obviously this requires a import java.io.*; at the top of the class
Source: http://www.abbeyworkshop.com/howto/java/writeText/index.html

Categories