ArrayIndexOutOfBoundsException in Java when using split - java

I am trying to read file and split its line to get some context(Computer Name and Date), the code gives few lines of outputs then gives the following exception:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at FILE_MAIN.getComputerName(FILE_MAIN.java:34)
at FILE_MAIN.readFiles(FILE_MAIN.java:24)
at FILE_MAIN.main(FILE_MAIN.java:12)
Code:
import java.util.*;
import java.io.*;
import java.util.Scanner;
public class FILE_MAIN
{
public static void main(String[] args) throws FileNotFoundException
{
File folder = new File("folderName/");
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++)
{
readFiles(listOfFiles[i].getName());
}
}
public static void readFiles(String fileName) throws FileNotFoundException
{
FileReader dataFile = new FileReader("yukt/"+fileName);
try (Scanner FileRead = new Scanner(dataFile))
{
while (FileRead.hasNextLine() && FileRead.nextLine().isEmpty()==false)
{
String[] split;
String line = FileRead.nextLine();
split = line.split("\\|",-1);
String computerName=getComputerName(split[0]);
System.out.println(computerName);
}
}
}
public static String getComputerName(String splited)
{
String[] split1;
String[] split2;
split1=splited.split("\\:",-1);
split2=split1[1].split("\\ ",-1);
return("a");
}
public static String getDate(String splited)
{
String[] split1=splited.split("\\(",-1);
String[] split2=split1[1].split("\\ ",-1);
return(split2[0]);
}
}
The main function gets names of the files in a folder, and passes each file to the readFiles function where each line is split into 3 parts by a delimeter(|) and parts are send to getComputerName and getDate function which returns its values after further splitting the strings.
Here is an example of a line of the file, all the lines are similar to this:
[CD8C] ComputerName:NITIN UserID:GO ankurjain Station 9900 LanId: | (11/24 19:50:30) | Client is disconnected from agent.

There is no protection for split1 containing a single element:
split1=splited.split("\\:",-1);
split2=split1[1].split("\\ ",-1); // Accesses second element of split1
Add protection and decide if it is an error for there to be no : in the input string or just use whole string if no ::
split1=splited.split("\\:",-1);
if (split1.length > 1)
{
split2=split1[1].split("\\ ",-1);
}

split1=splited.split("\\:",-1);
split2=split1[1].split("\\ ",-1);
split1 must not be doing what you think.
i.e. it is not splitting, cos split1[1] is not valid.
You should really check the result of the first split before trying to use it's results.

I had similar issue where I had to check weather string sub part contains given string or not. But String in question had many variation. Instead of using if loop I used ternary operator -
StringUtils.containsIgnoreCase("Test String",
("split me".split(":").length > 1)
? "split me".split(":")[1] : "Can't split")

split2=split1[1] gives you java.lang.ArrayIndexOutOfBoundsException: 1 the error. The Array does not have 2 elements so index on 1 will throw an error.
You could add a check to make sure it has atleast 2 elements by putting the assignement in a if statement
if (split1.lenght > 1){
split2=split1[1].split("\\ ",-1);
}

Related

Parse filename by split() to compare two common fields

I need to extract String parts from each file in a folder(files) having the following extensions as png,jpg,jpeg,PNG,JPG,JPEG. The file naming convention is as below(These are 2 different files but the only thing they have in common is the TIMESTAMP which will be required to get the FILENAME:
AIRLINECODE_PARTNERCODE_INVOICENO_timestamp.FILETYPE
FILENAME.FILETYPE_timestamp
Example file names:
ET_PRH_4_20170309140404.png
gosalyn.png_20170309140404
After reading the field from the first, I need to write each of the capital fields to the database (for eg AIRLINECODE, PARTNERCODE to columns in db). I am looping to iterate through "eachFile" in "files". The capital words are depicting the fields which will be added to the columns in the database. So AIRLINE_CODE has a column in the db and ET will be placed in it and so on for the others.
The following is the code I have written so far, so could you kindly guide how I can compare the second file's timestamp with the first and storing it in a field called "timestamp". Your help will be much appreciated. Thank you
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
public class Pathnames {
public void readFilename() {
// try-catch block to handle exceptions
try {
File f = new File("C:\\Users\\rsaeed\\Desktop\\files");
FilenameFilter filter = new FilenameFilter() {
#Override
public boolean accept(File f, String name) {
return name.endsWith(".png") || name.endsWith(".PNG") || name.endsWith(".jpg") || name.endsWith(".JPG") || name.endsWith(".jpeg") || name.endsWith(".JPEG");
}
};
// using a File class as an array
File[] files = f.listFiles(filter);
if(files != null) {
for(File eachFile : files) {
String[] partsOfName = eachFile.getName().split("_|\\."); // this part is correct and giving result in array as [ET, PRH, 4, 20170309140404, png]
//System.out.println(Arrays.toString(partsOfName));
// the following is wrong so what should be the code here that each file with .png_ is split and timestamp stored in secondFile array after which I can compare the two timestamps
if(eachFile.getName().contains(".png_")) {
String[] secondFile = eachFile.getName().split("\\_");
System.out.println(Arrays.toString(secondFile));
}
final String timestamp = partsOfName[3];
//System.out.println(timestamp);
}
}
// Get the names of the files by using the .getName() method
for (int i = 0; i < files.length; i++) {
System.out.println(files[i].getName());
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
public static void main(String args[]) {
Pathnames p = new Pathnames();
p.readFilename();
}
}
I will first share with you a little hint
#Override
public boolean accept(File f, String name) {
// Here you can leave the toLowerCase() to easy your life for sake of comparison since PNG and png is the same for you (this doesn't change the original name)
name = name.toLowerCase();
return name.endsWith(".png") || name.endsWith(".jpg") || name.endsWith(".jpeg");
}
To finally split your secondFile (i'm guessing for what you write this was your difficulty)
I made a simply regex to split as you requested:
So gosalyn.png_20170309140404 will be stored as [gosalyn, png, 20170309140404]
This regex will solve your problem "\.|\_"
'\.' is for any '.'
'|' is just like || (or)
'\_' is for any '_'

Simple Java Textfile not parsing Correctly

I have a simple textfile:
type = "hello"
number = 66
type = "hey"
number = 77
I'm basically just checking to see if the string "type" is found in the textfile, if yes, I'd also like to get the values "hello" and "hey" i.e the types. However, my program doesn't work at all in that sense it all always prints no, when checking if "type" is in the file.
public static void main(String[] args) {
if(args.length == 1)
parseText(argv[0]); // call with textfile name
}
public void parseText(String inPath) {
try {
Scanner s = new Scanner(inPath);
while(s.hasNextLine()) {
if("type".equals(s.nextLine().trim()))
System.out.println("Yes");
else {
System.out.println("no");
}
}
}catch (Exception e ) {
System.out.println("\nFILE NOT FOUND");
}
}
Any help would be much appreciated.
if("type".equals(s.nextLine().trim()))
You really want to read the line of data from the file into a String so you can do processing on the string.
You want to know if the line starts with "type":
String line = s.nextLine()
if (line.startsWith("type"))
{
String value = line.substring(8);
System.out.println(value);
}
Check if the line starts with "type" (not is equal to "type").
if("type".equals(s.nextLine().trim()))
should be something like
String line = s.nextLine().trim();
if (line.startsWith("type"))

pass the argument of array from command line instead of scanner in java

I write the code in Java to get the arguments by scanner. I have several classes : ChartToHtml.java, ExecutionProperties.java, ExecutionV2.java, TestCase.java, TestCaseList.java, Section.java and all of them will be called from ImplTest.java.
They are working fine when I execute either from eclipse or command line by scanner. The problem is when I want to execute them via program arguments and pass the arguments in one single line. It considers the input as single String but I have to use a String[] as input for Section class.
Here are my Section class and ImplTest classes
public class Section {
Ini.Section root;
ArrayList<String> StringList = new ArrayList<String>();
ArrayList<TestCase> TCList = new ArrayList<TestCase>();
String sectionSearched;
String section;
String filenameSearched;
public Section (){
}
public Section (String filenameSearched, String sectionSearched) {
this.sectionSearched = sectionSearched;
this.filenameSearched = filenameSearched;
}
public ArrayList<String> findSection(String filename, String... wanted) throws IOException, IOException {
Ini myIni = new Ini(new File (filename));
for (String d : wanted) {
root = myIni.get(d);
for (String name : root.keySet()){
StringList.add(root.get(name));
}
}
return StringList;
}
public ArrayList<TestCase> convertStringToTestCase(ArrayList<String>StringList){
for ( int i = 0; i < StringList.size(); i++) {
String name = StringList.get(i) ;
TestCase tc = new TestCase (name);
TCList.add(tc);
}
return TCList;
}
public String[] getSection(int NumOfSec){
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("Input section name:");
section = scanner.nextLine();
for (int i =0; i<NumOfSec; i++){
String token[]= section.split(" ");
System.out.println(Arrays.toString(token));
return token;
}
}
}
}
My Main class
public class ImplTest {
public static void main(String[] args) throws IOException, ConfigurationException, TemplateException {
ExecutionV2 ex = new ExecutionV2();
TestCaseList tc = new TestCaseList();
Section s = new Section();
ChartToHtml chr= new ChartToHtml();
ExecutionProperties ep = new ExecutionProperties();
ImplTest imp = new ImplTest();
String filename = ex.getcfg();
String []sec = ex.getSection();
int it = ex.getIterationMax();
String runTCpath =ex.getRunTCdir();
String dir = chr.getChartDir();
ArrayList<TestCase> TClist = s.convertStringToTestCase(s.findSection(filename, sec));
ex.executeTestCaseList(TClist, it , runTCpath);
ex.getTCAttribute(TClist);
ep.setConfigProperties(tc.getTCPassed(), tc.getTCFailed());
chr.generateHistoryTable();
chr.generateChartAndTableTemplate(tc.getTCPassed(), tc.getTCFailed(),ex.getNameList(), ex.getPassedList().toString(), ex.getItList().toString(),dir);
}
}
Then I modified the main class to pass the arguments via run configuration and pass this single line:
ArrayList<TestCase> TClist = s.convertStringToTestCase(s.findSection(**args[0]**, **args[1]**));
ex.executeTestCaseList(TClist, Integer.parseInt(**args[2]**) , **args[3]**);
ex.getTCAttribute(TClist);
ep.setConfigProperties(tc.getTCPassed(), tc.getTCFailed());
chr.generateHistoryTable();
chr.generateChartAndTableTemplate(tc.getTCPassed(), tc.getTCFailed(),ex.getNameList(), ex.getPassedList().toString(), ex.getItList().toString(), **args[4]**);
and pass this singe line into program arguments
C:\\Users\\syuniyar\\.EasyTest\\4\\ccl\\config\\test2.cfg 12346 5 C:\\EasyTest\\4\\bin\\runTC.exe C:\\Users\\syuniyar\\EclipseWS\Test3\\chart.html
it is working fine. However, when I modify the input from ...12346... to ...12346 12345..., I get such error:
Exception in thread "main" java.io.IOException: Cannot run program "5": CreateProcess error=2, The system cannot find the file specified
I also try with VM arguments but the option of System.getProperty() is only for single string.
I know why I get this error because it reads 12345 as 'it' which is not correct. What I wanna ask :
Is it possible to have an array as single argument in main method?
To directly answer your question, "Is it possible to have an array as [a] single argument in [a] main method?", no. The main method accepts arguments in the form of one array of String objects (usually called "args"). Each of these strings is considered an argument.
When executing the main method from the command line, these arguments come after the program name and are delimited by spaces. They are loaded into an array and passed into the main method.
As mentioned in the comments (esp. #Ismail Kuruca), if it is important to you to pass in several strings as one argument, you can concatenate the strings to make your arguments technically one String, and thereby treated as one argument.

Split string not working properly

I have trouble splitting a name by a space, and I can't seem to figure out why. Could someone please provide me with a solution?
My code is like this:
public void getPlayerNames(int id){
try {
Document root = Jsoup.connect("http://www.altomfotball.no/element.do?cmd=team&teamId=" + id).get();
Element table = root.getElementById("sd_players_table");
Elements names = table.getElementsByTag("a");
for(Element name : names){
getPlayers().add(new Player(name.text()));
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
which returns the name of football players as a string. The names are retrieved such as Mario Balotelli, Steven Gerrard, and so on, and I assumed I could use string.split(" "); to get me the first and last names, but whenever I try to access the second space of the string array it gives me an index out of bounds exception. Here is the code trying to fetch me the first name
/**
* Method to get the first name of a player
*/
public static String getFirstName(String name){
String[] nameArray = name.split(" ");
return nameArray[0];
}
Thanks for answers!
Sindre M
EDIT ######
So I got it to work, but thanks for the effort. The problem was that even though I could not see it in a simple sysout statement, the names actually contained a "&nbsp"; character, so I solved it by running a replaceAll("&nbsp ;" , " ") on the names for a better formatting.
If you're trying to write a screen-scraper you need to be more defensive in your code... Definitely test the length of the array first and log any unexpected inputs so you can incorporate them later...
public static String getFirstName(String name) {
String[] nameArray = name.split(" ");
if (nameArray.length >= 1) { // <== check length before you access nameArray[0]
return nameArray[0];
} else {
// log error
}
return null;
}
Additionally java.util.Optional in Java 8 provides a great alternative to returning null...
public static Optional<String> getFirstName(String name) {
String[] nameArray = name.split(" ");
if (nameArray.length >= 1) {
return Optional.of(nameArray[0]);
} else {
// log error
}
return Optional.empty();
}
You might be getting in the actual string as you are retrieving from html page. try to debug and check.
package com.appkart.examples;
public class SplitProgram {
public void firstNameArray(String nameString) {
String strArr[] = nameString.split(",");
for (String name : strArr) {
String playerName = name.trim();
String firstName = playerName.substring(0, playerName.indexOf(" "));
System.out.println(firstName);
}
}
public static void main(String[] args) {
String nameString = "Mario Balotelli, Steven Gerrard";
SplitProgram program = new SplitProgram();
program.firstNameArray(nameString);
}
}
I think that the correct answer should be:
String[] nameArray = name.split("\\s+");
But to be honest, there are couple of answers at stackoverflow.
Eg.
How to split a String by space
How do I split a string with any whitespace chars as delimiters?
First try to replace white space as
string.replace(" ","");
then try to split with [,] as
String strAr[] = string.split(",");

I keep getting the error: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0

When i try to run this code I keep getting this error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at Oblig3B.main(Oblig3B.java:8)
Here is my code:
import java.util.*;
import java.io.*;
class Oblig3B{
public static void main(String[]args){
OrdAnalyse oa = new OrdAnalyse();
Line 8. String filArgs=args[0];
oa.analyseMetode(filArgs);
}
}
class OrdAnalyse{
void analyseMetode(String filArgs){
Scanner input, innfil;
String[] ord;
int[] antall;
int antUnikeOrd, antOrd;
PrintWriter utfil;
boolean sjekk;
input=new Scanner(System.in);
ord=new String[5000];
antall=new int[5000];
antUnikeOrd=0;
antOrd=0;
sjekk=true;
try{
innfil=new Scanner(new File(filArgs));
//Here it reads the file, word by word.
while(innfil.hasNext()){
String ordLest=innfil.next().toLowerCase();
sjekk=false;
for(int i=0; i<ord.length; i++){
if(ordLest.equals(ord[i])){
antall[i]+=1;
sjekk=true;
}
}
if(!sjekk){
ord[antUnikeOrd]=ordLest;
antall[antUnikeOrd]++;
antUnikeOrd++;
}
antOrd++;
}
innfil.close();
}catch(Exception e){
e.printStackTrace();
}
try{
utfil=new PrintWriter(new File("Oppsummering.txt"));
utfil.println("Antall ord lest: " +antOrd+ " og antall unike ord: "+antUnikeOrd+"
"+ ord.length);
finnOrd(antall, ord, utfil);
for(int i=0; i<ord.length; i++){
utfil.println(ord[i]+(" ")+antall[i]);
}
utfil.close();
}catch(Exception e){
e.printStackTrace();
}
}
void finnOrd(int[] antall, String[] ord, PrintWriter utfil){
int teller=1000;
for(int i=0; i<ord.length; i++){
if(antall[i]>teller){
teller=antall[i];
}
double tiprosent=teller*0.90;
System.out.println(tiprosent + " " + teller);
for(i=0; i<ord.length; i++){
if(antall[i]>tiprosent){
utfil.println("Vanlige ord: "+ord[i]+"t("+antall[i]+" forekomster)");
}
}
}
}
}
I'm not sure what I need to do to fix this error. I would appreciate any help I can get.
(I'm sorry if the code is a bit messy, not sure how I can fix it properly here on stackoverflow)
Thanks alot
Java binds each argument passed to the application launched as an array to the String[] parameter in yourmain` method.
If you don't pass any arguments to the application launcher, for instance like
java Oblig3B
then the array bound will have size 0 and therefore
String filArgs = args[0];
trying to access the first element, at index 0, will fail. Check that you are actually passing arguments.
java Oblig3B "Some agument"
You didn't pass any command line arguments, so the args array is of zero-length. So, attempting any array access will throw an ArrayIndexOutOfBoundsException.
Test the length of the args array before attempting to access it. Here, make sure that the length is at least one before accessing args[0]. Something like:
if (args.length >= 1)
{
String filArgs=args[0];
// Do your processing.
}
else
{
// Handle the error here.
}
If you are running your program via command line you can pass one more parameter while running the command. If you are using an IDE e.g. eclipse you can pass the arguments by setting it via Properties -> Run/Debug settings
Basically, String filArgs=args[0]; is looking for first argument which doesn't exists

Categories