Testng. DataProvider. Read data in equal chunks from CSV file - java

Does anyone know, how to adjust TestNG's DataProvider reading from CSV-file in equal chunks, not sequentially in general?
General:
//Read data from CSV-file:
private static Object[][] getDataFromCSV(String fileNameroot) throws IOException {
List<Object[]> records = new ArrayList<>();
String record;
BufferedReader file = new BufferedReader(new InputStreamReader(new FileInputStream(fileNameroot), StandardCharsets.UTF_8));
file.readLine();
while ((record = file.readLine()) != null) {
String[] fields = record.split(", |,");
records.add(fields);
}
file.close();
Object[][] results = new Object[records.size()][];
for (int i = 0; i < records.size(); i++) {
results[i] = records.get(i);
}
return results;
}
Say, if we have 100 rows in file, so, it should (i.e. in 10 threads) for each thread read
firstly 1, 11, 21, ..., 91 rows
then 2, 12, 22, ..., 92
and so on...
till all 100 read
UPD:
Currently, only simultaneous 2-way file read (forward and backward (thanks to honorable responders by How to read file from end to start (in reverse order) in Java?)) achieved to meet each other near the middle of the file:
//2-way read data from CSV-file:
private static Object[][] getDataFromCSV(String fileNameroot) throws IOException {
List<Object[]> records = new ArrayList<>();
String record;
String recordReversed;//
long lineCount, lineCountMiddle, curr = 0, currReversed = 0, overlap = 1;
try (Stream<String> stream = Files.lines(Path.of(fileNameroot), StandardCharsets.UTF_8)) {
lineCount = stream.count();
lineCountMiddle = (long) Math.ceil(((double)lineCount)/2d) + overlap;
System.out.println("lineCount = "+ lineCount +",\n lineCountMiddle = "+ lineCountMiddle);
}
BufferedReader file = new BufferedReader(new InputStreamReader(new FileInputStream(fileNameroot), StandardCharsets.UTF_8));
BufferedReader fileReversed = new BufferedReader(new InputStreamReader(new ReverseLineInputStream(new File(fileNameroot)), StandardCharsets.UTF_8));//Important! got from: https://stackoverflow.com/q/8664705/11714800
while (curr < lineCountMiddle && currReversed < lineCountMiddle) {
record = file.readLine();
recordReversed = fileReversed.readLine();
String[] fields = record.split("[,]\\s?|,");
String[] fieldsReversed = recordReversed.split("[,]\\s?|,");
records.add(fields);
records.add(fieldsReversed);
++curr;
++currReversed;
}
file.close();
fileReversed.close();//
Object[][] results = new Object[records.size()][];
for (int i = 0; i < records.size(); i++) {
results[i] = records.get(i);
}
return results;
}

Related

How to get data from a CSV file and place it in a list

I want to read data from a CSV file in Java and then put this data into a list. The data in the CSV is put into rows which looks like:
Data, 32, 4.3
Month, May2, May 5
The code I have currently only prints the [32].
ArrayList<String> myList = new ArrayList<String>();
Scanner scanner = new Scanner(new File("\\C:\\Users\\Book1.csv\\"));
scanner.useDelimiter(",");
while(scanner.hasNext()){
myList.add(scanner.next());
for (int i = 0; i <= myList.size(); i++) {
System.out.println(myList.toString());
}
scanner.close();
}
Maybe this code can help you, maybe this code is different from yours, you use arrayList while I use regular array.
Example of the data:
Farhan,3.84,4,72
Rajab,2.98,4,72
Agil,2.72,4,72
Alpin,3.11,4,73
Mono,3,6,118 K
imel,3.97,7,132
Rano,2.12,6,110
Kukuh,4,1,22
Placing data on each row in a csv file separated by commas into the array of each index
int tmp = 0;
String read;
Mahasiswa[] mhs = new Mahasiswa[100];
BufferedWriter outs;
BufferedReader ins;
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
Scanner input = new Scanner(System.in);
try {
ins = new BufferedReader(new FileReader("src/file.csv"));
tmp = 0;
while ((read = ins.readLine()) != null) {
String[] siswa = read.split(",");
mhs[tmp] = new Mahasiswa();
mhs[tmp].nama = siswa[0];
mhs[tmp].ipk = Float.parseFloat(siswa[1]);
mhs[tmp].sem = Integer.parseInt(siswa[2]);
mhs[tmp].sks = Integer.parseInt(siswa[3]);
tmp++;
i++;
}
ins.close();
} catch (IOException e) {
System.out.println("Terdapat Masalah: " + e);
}
Print the array data
tmp = 0;
while (tmp < i) {
System.out.println(mhs[tmp].nama + "\t\t" +
mhs[tmp].ipk + "\t\t" +
mhs[tmp].sem + "\t\t" +
mhs[tmp].sks);
tmp++;
}
ArrayList<String> myList = new ArrayList<String>();
try (Scanner scanner = new Scanner(new File("C:\\Users\\Book1.csv"))) {
//here at your code there are backslashes at front and end of the path that was the
//main reason you are not able to read csv file
scanner.useDelimiter(",");
while (scanner.hasNext()) {
myList.add(scanner.next());
}
for (int i = 0; i < myList.size(); i++) { //remember index is always equal to "length - 1"
System.out.println(myList);
}
} catch (Exception e) {
e.printStackTrace();
}
you also did not handle the FileNotFoundException
Hope this helps:)

How do you convert a text file into a 2D character array?

I am trying to convert a text file into a 2 dimensional character array. I am part of the way there but the last line of my array is not fully correct. Here's my code:
protected void readMap(String fileName) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(fileName));
char[] chars;
int lines=0;
while (br.readLine() != null) {
lines++;
}
File file = new File(fileName);
try (FileReader reader = new FileReader(file)) {
chars = new char[(int) file.length()];
reader.read(chars);
reader.close();
} catch (IOException e) {
}
int columns = ((int) file.length())/lines;
map = new char[lines][columns];
for(int i=0; i<lines;i++){
for(int j=0;j<columns;j++){
map[i][j] = chars[j%columns+i*columns];
}
}
for(int ro=0; ro<map.length; ro++){
for(int colum=0; colum<(map[0].length); colum++){
System.out.print(map[ro][colum]);
}
}
return null;
}
Here's the output:
##########################
#........................#
#.....###........###.....#
#......G..........G......#
#........................#
#...........E............#
#......G.........G.......#
#........G.....G.........#
#..........###...........#
#........................#
#################
^missing #'s here
I'm very confused on why this is occuring. I've tried changing how I print the array but i'm pretty sure its how its to do with how i've converted the 1d 'chars' array to the 2d 'map' array.
I'm really lost so any help would be much appreciated! Thank you.
I'm guessing your file looks something like this
##########################
#........................#
#.....###........###.....#
#......G..........G......#
#........................#
#...........E............#
#......G.........G.......#
#........G.....G.........#
#..........###...........#
#........................#
##########################
If you print the file length, you will see that the file length is 296
As Your code row = 11 and columns = 26
When you are copying to map you are copying up to 11 * 26 = 286
Try the UPDATED code below
public void readMap(String fileName) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(fileName));
int lines = 0, columns = 0;
String str;
List<String> lineList = new ArrayList<>();
while ((str = br.readLine()) != null && str.length() != 0) {
lines++;
columns = Math.max(columns, str.length()); // as it's not fixed
lineList.add(str);
}
System.out.println("Row : " + lines);
System.out.println("Columns : " + columns);
char[][] map = new char[lines][columns];
for (int i = 0; i < lines; i++) {
String currentLine = lineList.get(i);
int idx = 0;
for (int j = 0; j < currentLine.length(); j++) {
map[i][j] = currentLine.charAt(idx++);
}
}
for (int r = 0; r < map.length; r++) {
for (int c = 0; c < (map[0].length); c++) {
System.out.print(map[r][c]);
}
System.out.println();
}
}
I've just executed the code and the map prints as expected. The issue may be down to the file itself as that is the uncommon factor.
edit:
The results you have observed is because you may have a new line character, or other special character, at the end of or somewhere in the file. Removing this you should see the consistent map you want.
Alternative
protected static void readMap(String fileName) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line = "";
List<String> lines = new ArrayList<>();
while ((line = br.readLine()) != null) {
lines.add(line);
}
char[][] chars = new char[lines.size()][];
for (int col = 0; col < lines.size(); col++) {
for (int row = 0; row < lines.get(col).length(); row++) {
chars[col] = lines.get(col).toCharArray();
}
}
for (int col = 0; col < chars.length; col++) {
for (int row = 0; row < chars[col].length; row++) {
System.out.print(chars[col][row]);
}
System.out.println();
}
}//My rows and cols may be back to front
Few other notes:
You shouldn't be returning a value from a void method, even null (You'll want to return null if the return type is Void).
Your compiler may complain if you don't initialize chars initially, as mine did. char[] chars = null; would do it in this scenario.

Writing an ArrayList to BufferedWriter using charArray()

The code snippet splits a CSV file into multiple CSV files and writes the first column content to the child CSV files. What I observed with this code is the column header "UNIQUE ID" is only appearing in FIRST CSV file. The following CSV files only contains data without the header. In order to get header to all files I thought of using an ArrayList so that I can put the header at the first index of ArrayList and rest of data afterwards. But I failed miserably.
I require suggestion or help for how to modify the code so that all the child files should have an additional UNIQUE IDENTIFIER row along as the first row with the column data. I am pasting the code which I tried and didn't work. Child csv should look like this This is what I am getting
public static void myFunction(int lines, int files) throws FileNotFoundException, IOException {
String inputfile = "C:/Users/Downloads/CONSOLIDATED.csv";
BufferedReader br = new BufferedReader(new FileReader(inputfile));
String strLine = null;
for (int i = 1; i <= files; i++) {
FileWriter fstream1 = new FileWriter("C:/Users/Downloads/FileNumber_" + i + ".csv");
BufferedWriter out = new BufferedWriter(fstream1);
for (int j = 0; j < lines; j++) {
strLine = br.readLine();
if (strLine != null) {
String strar[] = strLine.split(",");
ArrayList<String> al=new ArrayList<String>();
al.add(0,"Unique Identifier");
al.add(1,strar[0]);
char c[] = al.toString().toCharArray();
out.write(c);
out.newLine();
}
}
out.close();
}
br.close();
}
Your problem is that you are not keeping the headers out of the loops. Try something reading the first line before the main loop and store the headers in the List. then, every time you create a new file, before starting the inner loop, write the header in the first line of each file.
public static void myFunction(int lines, int files) throws FileNotFoundException, IOException {
String inputfile = "C:/Users/Downloads/CONSOLIDATED.csv";
BufferedReader br = new BufferedReader(new FileReader(inputfile));
String strLine = br.readLine(); //here you have the headers
String[] headers=strLine.split(",");
for (int i = 1; i <= files; i++) {
FileWriter fstream1 = new FileWriter("C:/Users/Downloads/FileNumber_" + i + ".csv");
BufferedWriter out = new BufferedWriter(fstream1);
out.write(headers[0]);
for (int j = 0; j < lines; j++) {
out.newLine();
strLine = br.readLine();
if (strLine != null) {
String strar[] = strLine.split(",");
out.write(strar[0]);
}
}
out.close();
}
br.close();
}

Dealing with txt file via split(), says Nullpointerexception

I know there are many similar questions here, but I still can't solve it. I can get all the results that I want. However, in the end, it still shows nullpointerexception. I don't know why. can anyone help?
public class PointGenterate {
public static void main(String[] args) throws FileNotFoundException {
// TODO Auto-generated method stub
try{
File file = new File("123.txt");
double[] pointsid = new double[10];
String[] data = null;
for(int i = 0; i <10; i++){
double rn = (int)(Math.random()*120);
System.out.println(rn);
pointsid[i] = rn;
}
//read file
InputStreamReader rs = new InputStreamReader(new FileInputStream(file));//create input stream reader object
BufferedReader br = new BufferedReader(rs);
String line = "";
line = br.readLine();
//
File write = new File("output.KML");
write.createNewFile();
BufferedWriter out = new BufferedWriter(new FileWriter(write));
while(line != null){
line = br.readLine();
if(line==" "){
System.out.print("empty");
}else{
data = line.split(",|:|[|]");
}
for(int i = 0; i < data.length; i++){
data[i] = data[i].trim();
System.out.println(data[i] + "num" + i);
}
if(data.length > 15){
double id = Double.parseDouble(data[4]);
for(int i = 0; i <10; i++){
if(id == pointsid[i]){
data[10] = data[10].substring(0, data[10].length()-2);
data[15] = data[15].substring(1,data[15].length());
data[16] = data[16].substring(0, data[16].length()-6);
out.write(data[8]+" "+ data[10]+ " " + data[13] + data[15] + data[16]+ "\r\n");
out.flush();
}
}
}
//System.out.println(line);
}
out.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
the txt file format is like
{ "type": "Feature", "properties": { "id": 126.000000, "osm_id": 4851918786.000000, "name": "Moray House Library", "type": "library" }, "geometry": { "type": "Point", "coordinates": [ -3.180841771200988, 55.950622362732418 ] } },
this is one line. I have many lines, and actually this is just a test code. if it works. i want to write it as a method in a javaseverlet class. get the string coordinates and return it to my JS font-end.
There's a few issues with your code. In this section:
InputStreamReader rs = new InputStreamReader(new FileInputStream(file));//create input stream reader object
BufferedReader br = new BufferedReader(rs);
String line = "";
line = br.readLine(); // here you read the first line in the file
//
File write = new File("output.KML");
write.createNewFile();
BufferedWriter out = new BufferedWriter(new FileWriter(write));
while(line != null){ // here you check that it's not null (it's not, you read the first line OK)
line = br.readLine(); // here you read the second line (there is no second line, now line is null)
if(line==" "){ // now you check if the line is a space character (this is wrong for 2 reasons, that's not how you compare strings, and a space character is not an empty string)
System.out.print("empty");
}else{
data = line.split(",|:|[|]"); // here you call split() on line but line is null
}
When you checked if the string was empty, you did line == " " which is wrong for 2 reasons. First you cannot use == to compare strings - read this question for details on why not. Second, " " is a string that contains a space character. "" is an empty string.
When you want to check if a string is empty you can do it like this:
line.equals("")
or like this:
line.isEmpty()
Here's your code with a few small changes so that it runs without throwing an exception.
public class PointGenterate {
public static void main(String[] args) throws Exception {
try {
File file = new File("123.txt");
double[] pointsid = new double[10];
String[] data = null;
for(int i = 0; i < 10; i++){
double rn = (int)(Math.random()*120);
System.out.println(rn);
pointsid[i] = rn;
}
//read file
InputStreamReader rs = new InputStreamReader(new FileInputStream(file));//create input stream reader object
BufferedReader br = new BufferedReader(rs);
String line = "";
//
File write = new File("output.KML");
write.createNewFile();
BufferedWriter out = new BufferedWriter(new FileWriter(write));
while((line = br.readLine()) != null){ // read the line and check for null
if(line.isEmpty()) { // is the line equal to the empty string?
System.out.print("empty");
} else {
data = line.split(",|:|[|]");
}
for(int i = 0; i < data.length; i++){
data[i] = data[i].trim();
System.out.println(data[i] + "num" + i);
}
if(data.length > 15){
double id = Double.parseDouble(data[4]);
for(int i = 0; i <10; i++){
if(id == pointsid[i]){
data[10] = data[10].substring(0, data[10].length()-2);
data[15] = data[15].substring(1,data[15].length());
data[16] = data[16].substring(0, data[16].length()-6);
out.write(data[8]+" "+ data[10]+ " " + data[13] + data[15] + data[16]+ "\r\n");
out.flush();
}
}
}
//System.out.println(line);
}
out.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}

Change number of split

Today, my code works but it makes a split of 2 lines by 2 lines, but that's not the goal.
I want to change the split, i want to divide 50 lines by 50 lines and not 2 by 2.
If I leave like that, I have three files of 2 lines
If i have 135 lines, i want:
Fist file: 50 lines (line 1-50 of my file) and the file name is 801.
Second file: 50 lines (line 51-100 of my file) and the file name is 802.
Third file: 35 lines (line 101-135 of my file) and the file name is 803.
Here, it is my code:
private void MyCode(ProducerTemplate producerTemplate, InputStream content, String endpoint, String fileName, HashMap<String, Object> headers){
ArrayList<String> list = new ArrayList<String>();
String line;
long numSplits = 50; //Number of lines per split
int sourcesize=0; //Number of lines
int number = 800; //my filename
BufferedReader br = new BufferedReader(new InputStreamReader(content));
try{
while((line = br.readLine()) != null){
sourcesize++;
list.add(line); //add the lines in the arraylist
}
System.out.println("Lines in the file: " + sourcesize);
for( int i = 0 ; i <= list.size() ; i+=numSplits) {
String Filename = ""+ number;
System.out.println(Filename);
StringBuilder builder = new StringBuilder();
builder.append(list.get(i)).append(System.lineSeparator()).append(list.get(i+1));
producerTemplate.sendBodyAndHeader(endpoint, builder.toString(), "CamelFileName",Filename); //Used to forward lines and the file name
}
} catch (IOException e) {
e.printStackTrace();
}
}
I think about:
for (int k=0;k<numSplits;k++) {
builder.append(list.get(i));
builder.append(System.lineSeparator());
}
How to change the split?
How can I cut my arraylist all 50 occurrences?
private void MyCode(ProducerTemplate producerTemplate, InputStream content, String endpoint, String fileName, HashMap<String, Object> headers){
BufferedReader br = new BufferedReader(new InputStreamReader(content));
ArrayList<String> list = new ArrayList<String>();
String line;
int numSplits = 50;
int number = 800;
int sourcesize=0;
try{
while((line = br.readLine()) != null){
sourcesize++;
list.add(line);
}
}
catch (IOException e){
e.printStackTrace();
}
System.out.println("Lines in the file: " + sourcesize);
ArrayList<ArrayList<String>> parts = cutListInChunksOfSameSize(list, numSplits);
for (ArrayList<String> part : parts){
String Filename = ""+ (number++);
System.out.println(Filename);
StringBuilder builder = new StringBuilder();
for( int i = 0 ; i <part.size() ;i++){
builder.append(part.get(i)).append(System.lineSeparator());
}
producerTemplate.sendBodyAndHeader(endpoint, builder.toString(), "CamelFileName",Filename);
}
}
public <T> ArrayList<ArrayList<T>> cutListInChunksOfSameSize(ArrayList<T> list, final int L) {
ArrayList<ArrayList<T>> parts = new ArrayList<ArrayList<T>>();
final int N = list.size();
for (int i = 0; i < N; i += L) {
parts.add(new ArrayList<T>(list.subList(i, Math.min(N, i + L))));
}
return parts;
}

Categories