This question already has answers here:
Number of lines in a file in Java
(19 answers)
Closed 4 years ago.
So basically, I'm trying to save several data saved from a file into an Array therefor I need to somehow get the size that the Array must be initialized to.
Is there any way to do that without creating another loop to count all the lines until the read line is null? Since that would require to re-open the file later which would not be very optimal. I'm trying to keep it as compact as possible.
Also, no I can't use ArrayLists.
I would go for an ArrayList, as Haroon and Hovercraft.
However, if it is not an option, why not :
// 1. Create a new Set of String
Set<String> stringSet = new HashSet<String>();
// 2. Loop through bufferedReader and add lines to set
for (String line = br.readLine(); line != null; line = br.readLine()) {
stringSet.add(line);
}
// 3. Copy set to a new array
int n = stringSet.size();
String array[] = new String[n];
array = stringSet.toArray(array);
But don't expect huge performances.
If you know in advance how many lines there will be you create the array before the loop and then you will need a counter which you use an an index into the array. You increment the counter each time through the loop.
If the number of lines is variable then add the lines to an ArrayList in the loop and then convert the ArrayList to an array after the loop
Related
I have a file of alphanumeric VIN numbers from vehicles (saved as strings). I need to parse through this file and determine
1) Is a VIN duplicated? If so, how many times
2) Write the duplicated VIN and the total number of duplicates to a text file
I have gotten it to work using the brute force method dual nested For loops. Am looking for a more elegant way to parse the strings. I'm using Java 7 in NetBeans 8.2 and it doesn't appear to like using the .set or hashmap.
Constraints
1) The VINs may be in any order
2) The duplicates can be scattered through the file at random
/* a) Open input and output files
*/
try {
inputStream = new BufferedReader(new FileReader(fileName));//csv file
outputStream = new PrintWriter(new FileWriter("DuplicateVINs.txt"));
/* b) Read in file line by line
then slice out the 17 digit VIN from the extra data I don't care about
*/
while ((thisLine = inputStream.readLine()) != null) {
l = thisLine.substring(1, 18);
linesVIN.add(l.split(","));//why does this split have to be here?
}
/*c) Now that the List is full calculate its size and then write to array of strings
*/
String[][] inputArray = new String[linesVIN.size()][];
i=linesVIN.size();
System.out.println(i);
linesVIN.toArray(inputArray);
/* d) Will use two nested For loos to look for duplicates
*/
countj=0;
countk=0;
for (int j = 1;j<=i-1; j++){ //j loop
duplicateVIN=Arrays.toString(inputArray[j]);
for(int k=1;k<=i-1;k++){
if(duplicateVIN.equals(Arrays.toString(inputArray[k]))){
countk=countk+1;
foundFlag=true;
} else{
//
if(countk>=2){
//if(j!=k){
System.out.println(duplicateVIN + countk);
//} // see if removes the first duplicate
}
foundFlag=false;
countk=0;
}
} //ends k loop
countj=j;
} //ends j loop
} //Completes the try
[2q3CDZC90JH1qqqqq], 3
[2q4RC1NG1JR1qqqqq], 4
[2q3CDZC96KH1qqqqq], 2
[1q4PJMDN8KD1qqqqq], 7
I'm using Java 7 in NetBeans 8.2 and it doesn't appear to like using the .set or hashmap.
Your first step should be to figure out what you're doing wrong with a map. A hashmap is the perfect solution for this problem, and is really what you should be using.
Here's a broad example of how the solution would work, using the information you provided.
Map<String,Integer> countMap = new HashMap<String,Integer>();
while ((thisLine = inputStream.readLine()) != null) {
l = thisLine.substring(1, 18);
if(countMap.containsKey(l)){
countMap.put(l, countMap.get(l)+1);
}else{
countMap.put(l,1);
}
}
I'm assuming that the while loop your provided is properly iterating over all VIN numbers.
After this while loop is completed you would just need to output the values of each key, similar to this:
for(String vin : countMap.keySet()){
System.out.println("VIN: "+vin+" COUNT: "+countMap.get(vin));
}
If I've read your problem correctly, there is no need for a nested loop.
Currently i am stuck up with a issue regarding comparing values in a text file. Below is my requirement which is a bit unique is what i can say.
I am getting a text file which is having data in the below format. The lines are a series of numbers of a particular format.
223---other line values
354---other line value
756---other line values
754---other line values
854---other line values
923---other line values
I have to validate that all the lines are starting in this order 2,3,7,8,9. There can be multiple lines in between 2 & 9 starting with 2,3,7,7,8,3,7,7,8,9. It is guranteed that 2 and 9 lines will be the first and last lines in the file. Multiple 7's can appear between 3 & 8.
I came up with the logic below for this comparison but the logic works for only one combination of lines starting with 2,3,7,7,8,9.
When there are multiple occurrences of lines like say 2,3,7,7,8,3,7,7,8,9 it does not work. Can someone please help me with what is wrong here and how i can solve this issue. If there is a better option or any other better way for my requirement please suggest so that i can use it. The volume in the input file is not high and can be almost 10 to 20 thousand.
Set<String> recordTypeOrder = new HashSet<>();
BufferedReader rdr = new BufferedReader(new StringReader("path to my file here"));
for (String line = rdr.readLine(); line != null; line = rdr.readLine()) {
if(line.startsWith("2")){
recordTypeOrder.add("2");
}else if(line.startsWith("3")){
recordTypeOrder.add("3");
}else if(line.startsWith("7")){
recordTypeOrder.add("7");
}else if(line.startsWith("8")){
recordTypeOrder.add("8");
}else if(line.startsWith("9")){
recordTypeOrder.add("9");
}
}
Set<String> orderToCompare = new TreeSet<>(recordTypeOrder);
boolean compare = orderToCompare.equals(actualOrder());
if(!compare){
logger.info("== Processing failed =====");
throw new CustomException("======= Processing failed =======");
}
private static Set<String> actualOrder(){
Set<String> actualOrder= new HashSet<>();
actualOrder.add("2");
actualOrder.add("3");
actualOrder.add("7");
actualOrder.add("8");
actualOrder.add("9");
return actualOrder;
}
Many Thanks
You need to store both order and count of 3,7,7,8. I think treeset won't work. Can you try others data structures like LinkedHashMap. That way you could just store the data you need in LinkedHashMap and then write a custom function to validate it.
This question already has answers here:
What's the simplest way to print a Java array?
(37 answers)
Closed 5 years ago.
ArrayList<String> nameList = new ArrayList<String>();
nameList.add("James");
nameList.add("Joe");
nameList.add("Josh");
nameList.add("Bob");
nameList.add("Billy");
System.out.println("The names are:\n " + nameList);
nameList.remove(1);
System.out.println("Find the index 1 and remove their name from the list:\n "+ nameList);
nameList.size();
System.out.println("Currently the ArrayList holds " + nameList.size() +
" names after removing the name of index 1" );
String[] tempArray= new String[nameList.size()];
tempArray = nameList.toArray(tempArray);
System.out.println(tempArray); // I want it to display the values of the ArrayList
}
}
The output I'm getting is [Ljava.lang.String;#4554617c when I want it to look like this [James, Josh, Bob, Billy]. New to programming would appreciate the help.
A couple of things.
Firstly, this code could be reduced.
String[] tempArray= new String[nameList.size()];
tempArray = nameList.toArray(tempArray);
could become
String[] tempArray= nameList.toArray(new String[nameList.size()]);
if I am not mistaken.
Secondly, an ArrayList automatically resizes itself with no code needed. How it does that is a whole new question.
And finally. The way objects are printed in Java is that if they are not primaries (int,bool,long,char...), they are printed using their .toString() method. On ArrayLists, this .toString() method returns a nice pretty representation of the list. But arrays don't define this method, and they instead get printed as some JVM dependent String. Instead, use Arrays.toString(tempArray) method. So your print statement would look like this:
System.out.println(Arrays.toString(tempArray));
Don't forget to import java.util.Arrays.
This question already has answers here:
How do I create a Java string from the contents of a file?
(35 answers)
Closed 6 years ago.
In Java, how would I convert an entire input file into one String?
In other words, if I have an input file "test.in":
c++
java
python
test
then I want to create a String containing "c++javapythontest".
I thought of something along the lines of
Scanner input = new Scanner(new File("test.in"));
while(input.hasNext()){
String test = test + input.nextLine();
}
but that doesn't seem to work.
Is there an efficient way to do this?
To read file contents, discarding newline chars:
String contents = Files.lines(Paths.get("test.in")).collect(Collectors.joining());
I think you needed to test for hasNextLine(), and your code's performance suffers from the creation of so many objects when you concatenate strings like that. If you changed your code to use a StringBuilder, it would run much faster.
There could be many ways to do it. One of the ways you can try is using the nio package classes. You can use the readAllBytes method of the java.nio.file.Files class to get a byte array first and then create a new String object from the byte array new String(bytes).
Read the Java Doc of this method.
Following is a sample program:
byte[] bytes= Files.readAllBytes(Paths.get(filePath));
String fileContent = new String(bytes);
Declare the String test out of the loop, then iterate filling it.
This code is a small modification to your original logic.
StringBuilder creates a mutable sequence of characters which means we just append the content to the value of StringBuilder object instead of creating a new object everytime.
In your code String test = test + input.nextLine(); was inside while loop.
Thus fresh objects of String test were created with every iteration of while loop and therefore it was not saving previous values.
String path = "test.txt";
Scanner input = new Scanner(new File(path));
StringBuilder sb = new StringBuilder();
while (input.hasNext()) {
sb.append(input.nextLine() + "\n");
}
System.out.println(sb.toString());
You can try this instead.
Its a simple one liner
String str = new String(Files.readAllBytes(Paths.get("/path/to/file")));
This reads the entire file and keeps it as String.
If you want to remove new line characters.
str.replace("\n", "");
String.join has been added in Java8 which internally uses StringBuilder
String content = String.join("", Files.readAllLines(Paths.get("test.in")));
i dont't use java very often and now i got some Problem.
I want to read a CSV file like this one:
A,B,C,D
A,B,F,K
E,F,S,A
A,B,C,S
A,C,C,S
Java don't know dynamic arrays, so i choose an ArrayList. This works so far. The Problem is:
How can I store the ArrayList? I think an other ArrayList would help.
This is what I got:
BufferedReader reader = new BufferedReader(
new InputStreamReader(this.getClass().getResourceAsStream(
"../data/" + filename + ".csv")));
List rows = new ArrayList();
String line;
while ((line = reader.readLine()) != null) {
rows.add(Arrays.asList(line.split(",")));
}
Now I get an ArrayList with a size of 5 for rows.size().
How do I get row[0][0] for example?
What do I want to do? The Problem is i want to find the same row except the last column.
For example i want to find row 0 and row 3.
thank you very much
Thank you all! You helped me a lot. =) Maybe Java and I will become friends =) THANKS!
You don't need to know the row size in advance, String.split() returns a String array:
List<String[]> rows = new ArrayList<String[]>();
String line = null;
while((line = reader.readLine()) != null)
rows.add(line.split(",", -1));
To access a specific row:
int len = rows.get(0).length;
String val = rows.get(0)[0];
Also, are you always comparing by the entire row except the last column? You could just take off the last value (line.replaceFirst(",.*?$", "")) and compare the rows as strings (have to be careful of whitespace and other formatting, of course).
A slightly different way:
Set<String> rows = new HashSet<String>();
String line = null;
while((line = reader.readLine()) != null){
if(!rows.add(line.substring(0, line.lastIndexOf(','))))
System.out.println("duplicate found: " + line);
}
Of course, modify as necessary if you actually need to capture the matching lines.
You'll need to declare an ArrayList of arrays. Asuming that csv file has a known number of columns, the only dynamic list needed here are the "rows" of your "table", formed by an ArrayList(rows) of arrays char[] (columns). (If not, then an ArrayList of ArrayList is fine).
It's just like a 2D table in any other language: an array of arrays. Just that in this case one of the arrays needs to be dynamic.
To read the file you'll need two loops. One that reads each line, just as you're doing, and another one that reads char per char.
Just a quick note: if you are going to declare an array like this:
char[] row = new char[5];
and then going to add each row to the ArrayList like this:
yourList.add(row);
You will have a list full of pointers to the same array. You'll need to use the .clone() method like this:
yourList.add(row.clone());
To access it like table[1][2], you'll need to use arraylist.get(1).get(2);