Short story: I generate random numbers and end symbol 0-9/ ( '/' is line end symbol, if I meet it, I go to write to next line in file.) When I generated my numbers and put in file, I want to get back those numbers from file but in not like strings, it should be Integers.
Assume my file looks like this:
846525451454341*
*
0067617354809629733035*
3313449117867514*
02337436891267261671546*
469980603887044*
7*
9*
642*
*
0617044835719095066*
5*
7175887168189821760*
581*
76300152922692817*
As you can noticed, line is able to hold only '*' in some cases (As I said it is generated random).
My purpose
I want to get back these lines like integers. For example I take 1 line until I meet end symbol ( '/' ) then I loop another line and so on.
Some snippet:
public void readGeneratedFile() throws IOException {
try(BufferedReader r= new BufferedReader(new FileReader("C:\\java\\numbers.txt"))){
int ch;
s = new String();
while((ch=r.read())!=-1){
s+=String.valueOf(Character.toChars(ch)).replace(" ",""); // Here I take all file into String, But this approach is leading to boilerplate code;
}
// catch IOException , finally close the file.
My question
How can I get back those lines like integers? (Suppose I want to take some actions with those numbers) It's cool if you get an idea what I want to do.
Thanks.
EDITED:
Sorry for misunderstanding, It is not what I want. I want to get back separated values, For example I have 123456/564654/21 string, and my Integer array[1][index] should looks like 1,2,3,4,5,6 then I meet end line symbol '/' I jump to array[2][index] and fill it with next line in file.
You can try like this. also.
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
BigInteger integer;
while (line != null) {
line = line.replace("*","");
integer = new BigInteger(line);
//Your stuf
line = br.readLine();
}
} finally {
br.close();
}
Your Strings are crossing the integer limit , You need BigInteger
Ex
BigInteger b = new BigInteger("7175887168189821760");
And you cannot get it back like integers since they are crossing the limit.
Use a StringBuilder as char accumulator (StringBuilder.append()) and finally
int result = Integer.parseInt(builder.toString());
This will help
Integer.parseInt(String)
Since you have bigger values greater than what an Integer can store, you can go for
Long.parseLong(String)
The other way is to use BigInteger(String) for working on the big numbers
Related
I have a String array containing a poem which has deliberate spelling mistakes. I am trying to iterate through the String array to identify the spelling mistakes by comparing the String array to a String array containing a dictionary. If possible I would like a suggestion that allows me to continue using nested for loops
for (int i = 0; i < poem2.length; i++) {
boolean found = false;
for (int j = 0; j < dictionary3.length; j++) {
if (poem2[i].equals(dictionary3[j])) {
found = true;
break;
}
}
if (found==false) {
System.out.println(poem2[i]);
}
}
The output is printing out the correctly spelt words as well as the incorrectly spelt ones and I am aiming to only print out the incorrectly spelt ones. Here is how I populate the 'dictionary3' and 'poem2' arrays:
char[] buffer = null;
try {
BufferedReader br1 = new BufferedReader(new
java.io.FileReader(poem));
int bufferLength = (int) (new File(poem).length());
buffer = new char[bufferLength];
br1.read(buffer, 0, bufferLength);
br1.close();
} catch (IOException e) {
System.out.println(e.toString());
}
String text = new String(buffer);
String[] poem2 = text.split("\\s+");
char[] buffer2 = null;
try {
BufferedReader br2 = new BufferedReader(new java.io.FileReader(dictionary));
int bufferLength = (int) (new File(dictionary).length());
buffer2 = new char[bufferLength];
br2.read(buffer2, 0, bufferLength);
br2.close();
} catch (IOException e) {
System.out.println(e.toString());
}
String dictionary2 = new String(buffer);
String[] dictionary3 = dictionary2.split("\n");
Your basic problem is in line
String dictionary2 = new String(buffer);
where you ware trying to convert characters representing dictionary stored in buffer2 but you used buffer (without 2 suffix). Such style of naming your variables may suggest that you either need a loop, or in this case separate method which will return for selected file array of words it holds (you can also add as method parameter delimiter on which string should be split).
So your dictionary2 held characters from buffer which represented poem, not dictionary data.
Another problem is
String[] dictionary3 = dictionary2.split("\n");
because you are splitting here only on \n but some OS like Windows use \r\n as line separator sequence. So your dictionary array may contain words like foo\r instead of foo which will cause poem2[i].equals(dictionary3[j] to always fail.
To avoid this problem you can split on \\R (available since Java 8) or \r?\n|\r.
There are other problems in your code like closing resource within try section. If any exception will be thrown before, close() will never be invoked leaving unclosed resources. To solve it close resources in finally section (which is always executed after try - regardless if exception will be thrown or not), or better use try-with-resources.
BTW you can simplify/clarify your code responsible for reading words from files
List<String> poem2 = new ArrayList<>();
Scanner scanner = new Scanner(new File(yourFileLocation));
while(scanner.hasNext()){//has more words
poem2.add(scanner.next());
}
For dictionary instead of List you should use Set/HashSet to avoid duplicates (usually sets also have better performance when checking if they contain some elements or not). Such collections already provide methods like contains(element) so you wouldn't need that inner loop.
I copied your code and ran it, and I noticed two issues. Good news is, both are very quick fixes.
#1
When I printed out everything in dictionary3 after it is read in, it is the exact same as everything in poem2. This line in your code for reading in the dictionary is the problem:
String dictionary2 = new String(buffer);
You're using buffer, which was the variable you used to read in the poem. Therefore, buffer contains the poem and your poem and dictionary end up the same. I think you want to use buffer2 instead, which is what you used to read in the dictionary:
String dictionary2 = new String(buffer2);
When I changed that, the dictionary and poem appear to have the proper entries.
#2
The other problem, as Pshemo pointed out in their answer (which is completely correct, and a very good answer!) is that you are splitting on \n for the dictionary. The only thing I would say differently from Pshemo here is that you should probably split on \\s+ just like you did for the poem, to stay consistent. In fact, when I debugged, I noticed that the dictionary words all have "\r" appended to the end, probably because you were splitting on \n. To fix this, change this line:
String[] dictionary3 = dictionary2.split("\n");
To this:
String[] dictionary3 = dictionary2.split("\\s+");
Try changing those two lines, and let us know if that resolves your issue. Best of luck!
Convert your dictionary to an ArrayList and use Contains instead.
Something like this should work:
if(dictionary3.contains(poem2[i])
found = true;
else
found = false;
With this method you can also get rid of that nested loop, as the contains method handles that for you.
You can convert your Dictionary to an ArrayList with the following method:
new ArrayList<>(Arrays.asList(array))
I have 3 String fields per line within my text file. There are 4 lines in total. The first 2 fields (field[0] and field[1]) are already filled in but field 3 (field[2]) is yet to be generated so it shall remain empty. Is there any way I can read in this text file line by line without getting a java.lang.ArrayIndexOutOfBoundsException: 1 error? I have included my code used for reading in the file.
import java.io.*;
public class PassGen {
public static void main(String args[]) throws Exception{
BufferedReader inKb = new BufferedReader(new InputStreamReader(System.in));
BufferedReader inF = new BufferedReader(new FileReader(new File("students.txt")));
String line = inF.readLine();
int cnt = 0;
Student pupil[] = new Student[6];
while(line != null) {
String field[] = line.split("//s");
pupil[cnt] = new Student(field[0], field[1], field[2]);
cnt++;
inF.readLine();
}
}
}
You can simply add a check on the number of fields:
if(field.length > 2) {
pupil[cnt] = new Student(field[0], field[1], field[2]);
} else {
pupil[cnt] = new Student(field[0], field[1], null);
}
Alternatively, you can use the overloaded split method that takes a limit parameter and set that to -1 to include the empty field. From the documentation of String#split(String regex, int limit):
The limit parameter controls the number of times the pattern is applied and therefore affects the length of the resulting array. If the limit n is greater than zero then the pattern will be applied at most n - 1 times, the array's length will be no greater than n, and the array's last entry will contain all input beyond the last matched delimiter. If n is non-positive then the pattern will be applied as many times as possible and the array can have any length. If n is zero then the pattern will be applied as many times as possible, the array can have any length, and trailing empty strings will be discarded.
Note that you need to use \\s instead of //s for the whitespace regex (this needs to be corrected either way).
String field[] = line.split("\\s", -1);
I think you problem lies in the way you are managing your data, but you can have something like this to read from any array and not getting any exceptions:
public static String getIfExists(final String[] values, final int position) {
return (values != null) && (values.length > position) ? values[position] : null;
}
Then you can fill every field like new Student(getIfExists(field, 0), getIfExists(field, 1), getIfExists(field, 2));
Of course you can optimize this a little bit more...but that would make the trick without having to think on how many fields you might get in the future or having a lot of if/case conditions.
I have space separated integers in one line and want to input them using BufferedReader. ** There may be more than one spaces between the integers. There may be leading and trailing spaces**
Right now I have following code ,
`
int[] a = new int[1000001]; // integer array
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n; // no of integers
int n = Integer.parseInt(br.readLine());
String[] s = br.readLine().split(" "); //taking input
for(int i=1;i<=n;++i)
{
a[i] = Integer.parseInt(s[i]);
}
`
Its not working.Please help. Any help or suggestion would be appreciated . Thanks.
Edit:1 - I used split("\s+"). But this cares for more than one spaces between integers... What about leading and trailing spaces..?? How to deal with them..?
Use split("\\s+") it should do the trick. It tells split() to use one or more space characters as a delimiter between two tokens.
Also you should allocate you int[] after you have read the number of int to read instead of allocating one that is way too big, you waste memory for nothing
You can first read the line, then use a regex to replace all whitespace with only one space. Then you can split it as you do above. Let me know if you need further help or code examples.
Edit: the NumberFormatException could be because the Integer.parseInt is trying to parse something outside of the value of an integer. Try Long.parseLong instead.
I am building a validation routine that validates contents and then gives warning (for failures) in form of StringBuilder. Say in below code I am checking lower bound for values paramX and paramY.
StringBuilder sb= new StringBuilder();
if(paramX<10){
sb.append("paramX cannot be less than 10 ");
}
if(paramY<20){
sb.append("paramY cannot be less than 20 ");
}
System.out.println(sb);
It gives output as: paramX cannot be less than 10 paramY cannot be less than 20
but i want output such that, each appended String will be printed on new line. Like below.
paramX cannot be less than 10
paramY cannot be less than 20
I used following workarounds, but ended up repeating same code again and again(Which i don't want to).
sb.append(System.getProperty("line.separator")); // Add Explicit line separator each time
sb.append("\n");
sb.append("paramX cannot be less than 10 \n");
Is there a simpler way to do it?
If you don't want to do it over and over then write a helper method:
public void appendString(StringBuilder builder, String value) {
builder.append(value + System.lineSeparator());
}
Then call:
if(paramX<10){
appendString(sb, "paramX cannot be less than 10 ");
}
This way you only have a single place to maintain if you need to change the output format for the errors.
Another option is to use Apache Commons StrBuilder, which has the functionality that you're looking for.
StrBuilder.appendLn()
The simple way would be to keep a list of errors rather than concatenating them as you go. That would help to maintain a separation of concerns between the logical errors and their presentation.
See how Spring validation works: you have an Errors object that keeps a list of errors, and a separate message source object that fills in the user-visible messages for the different errors.
Just thought of sharing the new feature of jdk 8 i used for achieving same result.
Using StringJoiner we can construct a sequence of characters separated by a delimiter.
StringJoiner formattedString= new StringJoiner("\n");
formattedString.add("XXX");
formattedString.add("YYY");
System.out.println(formattedString);
You could try using a PrintStream as it has an println(String string) method which add the new line automatically.
Something like this.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(bos);
ps.println("Line 1");
ps.println("Line 2");
ps.flush();
String message = new String(bos.toByteArray());
System.out.println(message);
First of all you need to include the newline character(\n) at the end of every .append() yourself:
sb.append("paramX cannot be less than 10 \n");
As for repeating you new-line logic just wrap it in a method:
public void append(StringBuilder sb, Object value) {
sb.append(value).append(System.getProperty("line.separator")).append('\n');
}
And use it like:
if(paramX < 10){
append(sb, "paramX cannot be less than 10");
}
simply append directly...
if(paramX<10){
sb.append("paramX cannot be less than 10 \n ");
}
if(paramY<20){
sb.append("paramY cannot be less than 20 \n ");
}
Just use \n - it will work everywhere. Also, it looks like you want to conditionally add a line feed if there are two messages:
StringBuilder sb = new StringBuilder();
if (paramX<10) {
sb.append("paramX cannot be less than 10 ");
}
if (paramY<20) {
if (!sb.length() > 0) // only add newline if needed
sb.append('\n');
sb.append("paramY cannot be less than 20 ");
}
Well, I am attempting to read a text file that looks like this:
FTFFFTTFFTFT
3054 FTFFFTTFFTFT
4674 FTFTFFTTTFTF
... etc
And when I am reading it, everything compiles and works wonderfully, putting everything into arrays like this:
studentID[0] = 3054
studentID[1] = 4674
... etc
studentAnswers[0] = FTFFFTTFFTFT
studentAnswers[1] = FTFTFFTTTFTF
However, if the studentID has a leading or trailing zero, when I print it with System.out.println();, it deletes the leading and trailing zeroes! I have a feeling this is something simple, and I need to like copy the array or something. Thank you :)
Below is my code:
public static String[] getData() throws IOException {
int total = 0;
int[] studentID = new int[127];
String[] studentAnswers = new String[127];
String line = reader.readLine();
String answerKey = line;
StringTokenizer tokens;
while((line = reader.readLine()) != null) {
tokens = new StringTokenizer(line);
studentID[total] = Integer.parseInt(tokens.nextToken());
studentAnswers[total] = tokens.nextToken();
System.out.println(total + " " +studentID[total]);
total++;
}
return studentAnswers;
}
Use String instead of int. As a general rule, use integral types for calculations.
If you want to preserve the zeroes, don't use parseInt on the student IDs; just store them as strings.
The int type has no concept of leading zeroes.
To add leading zeroes for display, use one of the format methods:
System.out.format("%04d", 80);
Integer.parseInt(tokens.nextToken()); will return the integer, so leading zeros will be omitted.
Have a look to the DecimalFormat class to handle parsing/formating of numbers.