I have a method that's reading a local CSV file and storing it in an array. I keep getting a ArrayIndexOutOfBoundsException when I try to print one of the index of the array.
The method:
public void getCsv() throws FileNotFoundException{
String fileName = "ADCSV.csv";
File file = new File(fileName);
Scanner inputStream = new Scanner(file);
while(inputStream.hasNext()){
String data = inputStream.next();
//array of strings
String[] values = data.split(",");
System.out.println(values[4]);
}
inputStream.close();
}
All of the information in the csv is stored as general text. When I try to print this is the output:
"adminCount"
"1"
"0"
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
at csvTest.test.getCsv(test.java:36)
at csvTest.test.main(test.java:19)
It starts to read the values from that particular column fine. It then errors out.
I feel like I've been looking at the problem for awhile now and looking right past the issue.
Thanks
Change your method to:
public void getCsv() throws FileNotFoundException {
String fileName = "ADCSV.csv";
File file = new File(fileName);
Scanner inputStream = new Scanner(file);
while (inputStream.hasNext()) {
String data = inputStream.next();
// array of strings
String[] values = data.split(",");
if (values.length < 5) {
System.err.println("not enough values: ");
for (int i = 0; i < values.length; i++) {
System.err.println("value " + i + ": " + values[i]);
}
continue;
}
System.out.println(values[4]);
}
inputStream.close();
}
That should show the problem. I mean it will print out the values of the line where the error will occur. Since we don't know what exactly produced the error this will be a start. Maybe somewhere is a comma where it shouldn't be or it is missing.
If the content of the local CSV file can contain errors then it would be appropriate to check the length of the splitted line and set up an error handling.
Related
My task is to read a text file in chunks of 64 characters, and use 2 different processes called Substitution and Column Transposition to encrypt it. Then, I have to decrypt it and write it out to another file.
I have written and tested out both processes of encrypting and decrypting and it worked wonderfully. But then I tried to loop the processes in case more than 64 characters were in the input file.
As a test case, I tried a 128 character input file. Unfortunately, the result only gives me the first 64 characters twice. I've tracked the scanner position and it goes beyond 64, but the characters read start back from 0. I'm not sure what the problem is.
Here is the relevant part of my code:
public static void main(String[] args) {
//Declare variables
Scanner console = new Scanner(System.in);
String inputFileName = null;
File inputFile = null;
Scanner in = null;
do
{
//Check if there are enough arguments
try
{
inputFileName = args[1];
}
catch (IndexOutOfBoundsException exception)
{
System.out.println("Not enough arguments.");
System.exit(1);
}
catch (Exception exception)
{
System.out.println("There was an error. Please try again.");
System.exit(1);
}
//Check if Input File is valid
try
{
inputFile = new File(inputFileName);
in = new Scanner(inputFile);
outputFile = new File(outputFileName);
out = new Scanner(outputFile);
}
catch (FileNotFoundException exception)
{
System.out.println("Could not find input file.");
System.exit(1);
}
catch (Exception exception)
{
System.out.println("There was an error. Please try again.");
System.exit(1);
}
} while (outputFileName != null && !inputFile.exists());
//Encryption
//Prepare patterns
String subPattern = CreateSubstitutionPattern(hash);
int[] transPattern = CreateTranspositionPattern(hash);
//Apply patterns
String textContent = "";
String applySub = "";
String applyTrans = "";
do
{
textContent = Read64Chars(in);
applySub = applySub + ApplySubstitutionPattern(textContent, subPattern);
applyTrans = applyTrans + ApplyTranspositionPattern(applySub, transPattern);
} while (in.hasNext());
//Decryption
String encryptContent = "";
Scanner encrypt = new Scanner(applyTrans);
String removeTrans = "";
String removeSub = "";
do
{
encryptContent = Read64Chars(encrypt);
System.out.println(applyTrans);
removeTrans = removeTrans + RemoveTranspositionPattern(encryptContent, transPattern);
removeSub = removeSub + RemoveSubstitutionPattern(removeTrans, subPattern);
} while (encrypt.hasNext());
console.close();
in.close();
encrypt.close();
System.out.println(removeSub); //For temporary testing
}
public static String Read64Chars (Scanner in)
{
String textContent = "";
in.useDelimiter("");
for (int x=0; x<64; x++)
{
if (in.hasNext())
{
textContent = textContent + in.next().charAt(0);
}
}
return textContent;
}
Do note that I have more variables to fill in args[0] and args[2] but I removed them for simplicity.
I would like to know if it is true that once a scanner reads a portion of it's input, it "consumes" it, and that portion gets removed. Does the scanner reset itself when declared again through a method? For example, does the declaration only point to the input source of the original scanner, or the actual scanner with its current properties?
encrypt is a diffrent Scanner from in, which you advance by 64 characters when you first call Read64Chars. So, encrypt starts at the first character when you call Read64Chars(encrypt). It seems like you want to use the same Scanner both times.
Also, in the future please name your functions starting with a lowercase letter. I felt dirty typing that... :)
A proper solution to get the whole encrypted text would be a code like this
public static String encryptedTextFile (Scanner in)
{
//ArrayList<String> stringBlocksOf64Chars = new ArrayList<String>();
StringBuilder encryptedTxt = new StringBuilder();
String currentTxt = "";
while (in.hasNextLine()) {
String line = currentTxt + in.nextLine();
currentTxt = "";
int i = 0;
for( ; i < line.length()/64 ; i++){
currentTxt = line.substring(i * 64, (i+1)*64);
//TODO - encrypt the text before adding it to the list
encryptedTxt.append(currentTxt);//encryptedTxt.append(encrypt(currentTxt));
}
currentTxt = line.substring(i * 64, line.length());
}
encryptedTxt.append(currentTxt);
/*for(String str : stringBlocksOf64Chars)
System.out.println(str);*/
return encryptedTxt.toString();
}
Your loop for (int x=0; x<64; x++) makes sure that you read only first 64 characters always and not the complete file. To get around that you should actually read whole file line by line.
The above code block follows this idea.
Steps to break down the logic.
Read the file line by line using scanner.
Break each line into chunks of 64 characters and encrypt the block 64 characters at a time
Generate encrypted text adding the encrypted 64 characters.
Whatever you do first break down the logic/steps you want to use in your code to make it simpler to understand or code.
Break the lines into 64 characters
I am new in java. I just wants to read each string in java and print it on console.
Code:
public static void main(String[] args) throws Exception {
File file = new File("/Users/OntologyFile.txt");
try {
FileInputStream fstream = new FileInputStream(file);
BufferedReader infile = new BufferedReader(new InputStreamReader(
fstream));
String data = new String();
while ((data = infile.readLine()) != null) { // use if for reading just 1 line
System.out.println(""+data);
}
} catch (IOException e) {
// Error
}
}
If file contains:
Add label abc to xyz
Add instance cdd to pqr
I want to read each word from file and print it to a new line, e.g.
Add
label
abc
...
And afterwards, I want to extract the index of a specific string, for instance get the index of abc.
Can anyone please help me?
It sounds like you want to be able to do two things:
Print all words inside the file
Search the index of a specific word
In that case, I would suggest scanning all lines, splitting by any whitespace character (space, tab, etc.) and storing in a collection so you can later on search for it. Not the question is - can you have repeats and in that case which index would you like to print? The first? The last? All of them?
Assuming words are unique, you can simply do:
public static void main(String[] args) throws Exception {
File file = new File("/Users/OntologyFile.txt");
ArrayList<String> words = new ArrayList<String>();
try {
FileInputStream fstream = new FileInputStream(file);
BufferedReader infile = new BufferedReader(new InputStreamReader(
fstream));
String data = null;
while ((data = infile.readLine()) != null) {
for (String word : data.split("\\s+") {
words.add(word);
System.out.println(word);
}
}
} catch (IOException e) {
// Error
}
// search for the index of abc:
for (int i = 0; i < words.size(); i++) {
if (words.get(i).equals("abc")) {
System.out.println("abc index is " + i);
break;
}
}
}
If you don't break, it'll print every index of abc (if words are not unique). You could of course optimize it more if the set of words is very large, but for a small amount of data, this should suffice.
Of course, if you know in advance which words' indices you'd like to print, you could forego the extra data structure (the ArrayList) and simply print that as you scan the file, unless you want the printings (of words and specific indices) to be separate in output.
Split the String received for any whitespace with the regex \\s+ and print out the resultant data with a for loop.
public static void main(String[] args) { // Don't make main throw an exception
File file = new File("/Users/OntologyFile.txt");
try {
FileInputStream fstream = new FileInputStream(file);
BufferedReader infile = new BufferedReader(new InputStreamReader(fstream));
String data;
while ((data = infile.readLine()) != null) {
String[] words = data.split("\\s+"); // Split on whitespace
for (String word : words) { // Iterate through info
System.out.println(word); // Print it
}
}
} catch (IOException e) {
// Probably best to actually have this on there
System.err.println("Error found.");
e.printStackTrace();
}
}
Just add a for-each loop before printing the output :-
while ((data = infile.readLine()) != null) { // use if for reading just 1 line
for(String temp : data.split(" "))
System.out.println(temp); // no need to concatenate the empty string.
}
This will automatically print the individual strings, obtained from each String line read from the file, in a new line.
And afterwards, I want to extract the index of a specific string, for
instance get the index of abc.
I don't know what index are you actually talking about. But, if you want to take the index from the individual lines being read, then add a temporary variable with count initialised to 0.
Increment it till d equals abc here. Like,
int count = 0;
for(String temp : data.split(" ")){
count++;
if("abc".equals(temp))
System.out.println("Index of abc is : "+count);
System.out.println(temp);
}
Use Split() Function available in Class String.. You may manipulate according to your need.
or
use length keyword to iterate throughout the complete line
and if any non- alphabet character get the substring()and write it to the new line.
List<String> words = new ArrayList<String>();
while ((data = infile.readLine()) != null) {
for(String d : data.split(" ")) {
System.out.println(""+d);
}
words.addAll(Arrays.asList(data));
}
//words List will hold all the words. Do words.indexOf("abc") to get index
if(words.indexOf("abc") < 0) {
System.out.println("word not present");
} else {
System.out.println("word present at index " + words.indexOf("abc"))
}
So I'm at a point in my program where I want to read from a csv file (which has two columns), do some light calculation on the first column (after I check whether or not it has any content), then print the new number (which I calculated from column 1 in the first file) and the contents of the second column from the original file to a new text file.
Without a while loop I have no trouble running calculations on the numbers from the original text file, then printing them to the new file. However ANY printing from inside the while loop is giving me an error. In fact, anything other than reading the file and parsing it into an array of strings is giving me an error from inside the while loop.
These are the top two lines of my stackTrace with the code I currently have posted below:
"Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0
at finalProyect.User.makeMealPlan(User.java:476)"
Line 476 being the line in my while loop: "if (array2[0].isEmpty())"
After hours of searching and tinkering I thought it was time to ask for help. Thanks in advance for any help you can provide.
public void makeMealPlan() {
String fileIn = "mealPlan1.csv";
Scanner inputStream = null;
String fileOut = userName + ".txt";
PrintWriter outputStream = null;
try {
inputStream = new Scanner(new File(fileIn));//opens and reads pre-configured meal plan
outputStream = new PrintWriter(fileOut);//creates output file for meal plan
} catch(FileNotFoundException e3) {
fileNotFound();
e3.printStackTrace();
}
outputStream.println(toString());
outputStream.println();
String line0 = inputStream.nextLine();
String[] array0 = line0.split(","); //Splits line into an array of strings
int baseCalories = Integer.parseInt(array0[0]); //converts first item in array to integer
double caloricMultiplier = (caloricNeeds / baseCalories); //calculates the caloricMultiplier of the user
String line1 = inputStream.nextLine();//reads the next line
String[] array1 = line1.split(",");//splits the next line into array of strings
outputStream.printf("%12s %24s", array1[0], array1[1]); //prints the read line as column headers into text file
while(inputStream.hasNextLine()) {
String line = inputStream.nextLine(); //reads next line
String[] array2 = line.split(",");
if(array2[0].isEmpty()) {
outputStream.printf("%12s %24s", array2[0], array2[1]);
} else {
double quantity = Double.parseDouble(array2[0]);
quantity = (quantity * caloricMultiplier);
outputStream.printf("%12s %24s", quantity, array2[1]);
}
}
outputStream.close();
System.out.println(toString());
}
Okay, so there were a few things wrong. However with #NonSecwitter's suggestion I was able to pin it down. So first thing (again as NonSecwitter mentioned) I had empty fields in my .csv which was throwing the ArrayIndexOutOfBounds" error. So what I did was I filled every empty field in my .csv with the string "empty". Once I did that I was able to at least print the next line.
After that, I ran into another error which was that this line:
double quantity = Double.parseDouble(array2[0]);
could not be separated from the the preceding read/split statements by being inside of an if-loop. So I ended up rewriting the guts of the entire while-loop and needed to throw an exception like so:
while (inputStream.hasNextLine())
{
String[] array2 = null;
try
{
String line = inputStream.nextLine(); //reads next line
array2 = line.split(",");
double quantity = Double.parseDouble(array2[0]);
if (!isStringNumeric(array2[0]))
throw new NumberFormatException();
quantity = Math.ceil(quantity * caloricMultiplier);
outputStream.printf("%12.1f %15s\n", quantity, array2[1]);
}
catch(NumberFormatException e1)
{
if (array2[1].equals("empty"))
outputStream.printf("%12s %15s\n", " ", " ");
else
outputStream.printf("%12s %15s\n", " ", array2[1]);
}
}
While my program is now currently working just fine, I'd still really appreciate an explanation as to why I ended up having to throw an exception to get the code to work. Are there certain restrictions with using PrintWriter inside of a while-loop? Also, I very much appreciate everybody's feedback. I think with all the comments/suggestions combined I was able to determine where my problems were (just not WHY they were problems).
Thanks!!!
It would help if you provided sample CSV data and an example of the related output you expect in <userName>.txt.
Short of this I can only help insofar as saying I do not get an exception with your code.
Here is what I got with a quick Java project in Eclipse using project and class-file names gleaned from your exception output (finalProyect and User.java respectively), pasting your code into the class file (User.java), and massaging it a bit for a sanity check...
package finalProyect;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Scanner;
public class User {
public void makeMealPlan()
{
String fileIn = "C:\\Temp\\mealPlan1.csv";//"mealPlan1.csv"; // FORNOW: adjusted to debug
Scanner inputStream = null;
String userName = "J0e3gan"; // FORNOW: added to debug
String fileOut = "C:\\Temp\\" + userName + ".txt"; // FORNOW: adjusted to debug
PrintWriter outputStream = null;
try
{
inputStream = new Scanner(new File(fileIn));//opens and reads pre-configured meal plan
outputStream = new PrintWriter(fileOut);//creates output file for meal plan
}
catch(FileNotFoundException e3)
{
//fileNotFound(); // FORNOW: commented out to debug
e3.printStackTrace();
}
outputStream.println(toString());
outputStream.println();
String line0 = inputStream.nextLine();
String[] array0 = line0.split(","); //Splits line into an array of strings
int baseCalories = Integer.parseInt(array0[0]); //converts first item in array to integer
int caloricNeeds = 2000; // added to debug
double caloricMultiplier = (caloricNeeds / baseCalories); //calculates the caloricMultiplier of the user
String line1 = inputStream.nextLine();//reads the next line
String[] array1 = line1.split(",");//splits the next line into array of strings
outputStream.printf("%12s %24s", array1[0], array1[1]); //prints the read line as column headers into text file
while (inputStream.hasNextLine())
{
String line = inputStream.nextLine(); //reads next line
String[] array2 = line.split(",");
if (array2[0].isEmpty())
outputStream.printf("%12s %24s", array2[0], array2[1]);
else
{
double quantity = Double.parseDouble(array2[0]);
quantity = (quantity * caloricMultiplier);
outputStream.printf("%12s %24s", quantity, array2[1]);
}
}
outputStream.close();
System.out.println(toString());
}
public static void main(String[] args) {
// FORNOW: to debug
User u = new User();
u.makeMealPlan();
}
}
...and an example of what it output to J0e3gan.txt...
finalProyect.User#68a6a21a
3000 40 2500.0 50 4000.0 25
...with the following (complete-WAG) data in mealPlan1.csv:
2000,20
3000,40
2500,50
4000,25
Comment out the offending code and try to println() array2[0] and see if it gives you anything.
while (inputStream.hasNextLine())
{
String line = inputStream.nextLine(); //reads next line
String[] array2 = line.split(",");
System.out.println(array2[0]);
//if (array2[0].isEmpty())
// outputStream.printf("%12s %24s", array2[0], array2[1]);
//
//else
//{
//
// double quantity = Double.parseDouble(array2[0]);
// quantity = (quantity * caloricMultiplier);
// outputStream.printf("%12s %24s", quantity, array2[1]);
//}
}
or, try to print the length. If the array were empty for some reason array2[0] would be out of bounds
System.out.println(array2.length);
I would also print line to see what it's picking up
System.out.println(line);
I am getting exception thrown and i think it has to with the ArrayIndexOutOfBounds at the sub string and also do you think the below method would work for getting data passed to my array after parsing
I want this to be read from a txt file like this, on each line:
1
0
1
0
0
1
0
ONE INTEGER PER LINE!!
String fileName = "input.txt";
File file = new File(fileName);
Scanner scanner = new Scanner(file);
while(scanner.hasNextLine()){
data1 = scanner.nextLine();
}
for ( int i = 0; i < data1.length(); i++)
{
covertDataArray[i] = Byte.parseByte(data1.substring( i, i+1));
}
This is previous working version but it reads from the console. where it would be : 1010101001
System.out.println("Enter the binary bits");
data1 = in.next();
for ( int i = 0; i < data1.length(); i++)
{
covertDataArray[i] = Byte.parseByte(data1.substring( i, i+1));
}
You're reading all the lines and only keeping the last in your data1 variable. That's probably your problem.
You should, instead, handle each value right away while reading the file, and build an ArrayList instead of an array (because you won't know its size beforehand):
String fileName = "input.txt";
File file = new File(fileName);
Scanner scanner = new Scanner(file);
ArrayList<Byte> covertDataList= new ArrayList<>();
while(scanner.hasNextLine()){
String line = scanner.nextLine(); // the line should be just a number
covertDataList.add(Byte.parseByte(line)); // no substring needed
}
If you want to fail nicely when the file format is wrong, you may surround parseByte with a try/catch block.
About the ArrayList
If you want to use your list as an array, you can just:
use covertDataList.get(i) instead of covertDataArray[i]
use covertDataList.set(i, value); instead of covertDataArray[i] = value;
If you really need an array (I don't see the point here), you can do this:
Byte[] covertDataArray = covertDataList.toArray(new Byte[list.size()]);
I have a text file with data. The file has information from all months. Imagine that the information for January occupy 50 lines. Than February starts and it occupies 40 more lines. Than I have March and so on... Is it possible to read only part of the file? Can I say "read from line X to line Y"? or is there a better way to accomplish this? I only want to print the data correspondent to one month not the all file. Here is my code
public static void readFile()
{
try
{
DataInputStream inputStream =
new DataInputStream(new FileInputStream("SpreadsheetDatabase2013.txt"));
while(inputStream.available() != 0)
{
System.out.println("AVAILABLE: " + inputStream.available());
System.out.println(inputStream.readUTF());
System.out.println(inputStream.readInt());
for (int i = 0; i < 40; i++)
{
System.out.println(inputStream.readUTF());
System.out.println(inputStream.readUTF());
System.out.println(inputStream.readUTF());
System.out.println(inputStream.readUTF());
System.out.println(inputStream.readUTF());
System.out.println(inputStream.readDouble());
System.out.println(inputStream.readUTF());
System.out.println(inputStream.readBoolean());
System.out.println();
}
}// end while
inputStream.close();
}// end try
catch (Exception e)
{
System.out.println("An error has occurred.");
}//end catch
}//end method
Thank you for your time.
My approach to this would be to read the entire contents of the text file and store it in a ArrayList and read only the lines for the requested month.
Example:
Use this function to read the all the lines from the file.
/**
* Read from a file specified by the filePath.
*
* #param filePath
* The path of the file.
* #return List of lines in the file.
* #throws IOException
*/
public static ArrayList<String> readFromFile(String filePath)
throws IOException {
ArrayList<String> temp = new ArrayList<String>();
File file = new File(filePath);
if (file.exists()) {
BufferedReader brin;
brin = new BufferedReader(new FileReader(filePath));
String line = brin.readLine();
while (line != null) {
if (!line.equals(""))
temp.add(line);
line = brin.readLine();
}
brin.close();
}
return temp;
}
Then read only the ones you need from ArrayList temp.
Example:
if you want to read February month's data assuming its 50 lines of data and starts from 40th line.
for(int i=40;i<90;i++)
{
System.out.println(temp.get(i));
}
Note: This is only just one way of doing this. I am not certain if there is any other way!
I would use the scanner class.
Scanner scanner = new Scanner(filename);
Use scanner.nextLine() to get each of the lines of the file. If you only want from line x to line y you can use a for loop to scan each of the lines that you don't need before going through the scanner for the lines you do need. Be careful not to hit an exception without throwing it though.
Or you can go through the scanner and for each line, add the String contents of the line to an ArrayList. Good luck.
Based on how you said your data was organized, I would suggest doing something like this
ArrayList<String> temp = new ArrayList<String>();
int read = 0;
File file = new File(filePath);
if (file.exists()) {
BufferedReader brin;
brin = new BufferedReader(new FileReader(filePath));
String line = brin.readLine();
while (line != null) {
if (!line.equals("")){
if(line.equals("March"))
read = 1;
else if(line.equals("April"))
break;
else if(read == 1)
temp.add(line);
}
line = brin.readLine();
}
brin.close();
Just tried it myself, that'll take in all the data between March and April. You can adjust them as necessary or make them variables. Thanks to ngoa for the foundation code. Credit where credit is due
If you have Java 7, you can use Files.readAllLines(Path path, Charset cs), e.g.
Path path = // Path to "SpreadsheetDatabase2013.txt"
Charset charset = // "UTF-8" or whatever charset is used
List<String> allLines = Files.readAllLines(path, charset);
List<String> relevantLines = allLines.subList(x, y);
Where x (inclusive) and y (exclusive) indicates the line numbers that are of interest, see List.subList(int fromIndex, int toIndex).
One benefit of this solution, as stated in the JavaDoc of readAllLines():
This method ensures that the file is closed when all bytes have been read or an I/O error, or other runtime exception, is thrown.