I need read data from csv file and much more convinience for me is put there to 2D array (to my mind it's easiest way to work with this "schedule" data).
Each file line contained information in following format:
Instructor, Course, Group, Student, Result
as follows example:
Paul Schwartz,Introduction to Computer Architecture,I1,Ben Dunkin,88
Muhamed Olji,Object Oriented Programming,I4,Mike Brown,73
But my code needs some simplify. But I don't know how to make it easier and ask of You.
Code:
private String[][] fileContent(String pathToCSVFile) {
final int ROWS = 100;
final int COLUMNS = 5;
String fileData[][] = new String[ROWS][COLUMNS];
Scanner scanner = new Scanner(pathToCSVFile);
boolean done = false;
int i, j;
while (!done) {
for (i = 0; i >= 0; i++) {
for (j = 0; j >= 0; j++) {
String str[] = scanner.nextLine().split(",");
for (int element = 0; element < str.length; element++) {
fileData[i][element] = str[element];
if (i >= ROWS) {
Arrays.copyOf(fileData, fileData.length * 2);
}
}
}
}
if (!scanner.hasNextLine()) done = true;
}
return fileData;
}
How to refactor this snippet of code for better simplicity?
Does exist any better way for partially filled array (than Arrays.copyOf(fileData, fileData.length * 2))?
Using openCSV, you can get a list containing all the lines and convert it to an array (or just keep the list):
try (CSVReader reader = new CSVReader(new BufferedReader(
new FileReader(pathToCSVFile)));) {
List<String[]> lines = reader.readAll();
return lines.toArray(new String[lines.size()][]);
}
(using Java 7 try-with-resources syntax)
First of all, be careful with those for loops. They are "almost" undefined loops, because they start with i,j=0, and loop while >=0 (always, until they overflow into a negative number).
And why do you need them anyway? I think with you while and the for(element) you are done, right?
Something like that (I didn't tried, is just to explain the concept)
private String[][] fileContent(String pathToCSVFile) {
final int ROWS = 100;
final int COLUMNS = 5;
String fileData[][] = new String[ROWS][COLUMNS];
Scanner scanner = new Scanner(pathToCSVFile);
boolean done = false;
int i=0;
while (!done) {
String str[] = scanner.nextLine().split(",");
for (int element = 0; element < str.length; element++) {
fileData[i][element] = str[element];
if (i >= ROWS) {
Arrays.copyOf(fileData, fileData.length * 2);
}
}
if (!scanner.hasNextLine())
done = true;
else
i++;
}
return fileData;
}
By the way, why don't you use objects, like an ArrayList? It would make your life easier, so you don't have to worry about memory handling. You just add new objects.
Something like an ArrayList <ArrayList <String>>
Related
this is a lab for class I'm trying to do. Here's the instructions:
Write a program that takes in a line of text as input, and outputs that line of text in reverse. The program repeats, ending when the user enters "Done", "done", or "d" for the line of text.
Ex: If the input is:
"Hello there
Hey
done"
the output is:
"ereht olleH
yeH"
And here's what I have right now:
public class LabProgram {
public static void main(String[] args) {
/* Type your code here. */
Scanner scnr = new Scanner(System.in);
String[] inputs = new String[100];
String input;
int i = 0;
while (true) {
input = scnr.nextLine();
if(input.equals("Done") || input.equals("done") || input.equals("d"))
break;
inputs[i] = input;
i++;
}
for (int j = 0; j < i; j++) {
int length = inputs[j].length();
String reverse = "";
for (int k = length - i; k >= 0; k--) {
reverse = reverse + inputs[j].charAt(k);
}
System.out.print("\n" + reverse);
}
}
}
Current output
What am I doing wrong??
Iterate through the array, and reverse elements at every index.
This solution is time consuming but does your job
for (int j = 0; j < inputs.lenght; j++) {
int length = inputs[j].length();
char a;
String rev = "";
for(int i =0; i< length; i++){
a = inputs[j].charAt(i);
rev = a + rev;
}
System.out.println(rev);
}
*Try to use StringBuilder And use method reverse -- #Artur Todeschini
To add to what Artur said, an ArrayList of StringBuilders could do the trick quite well:
for(StringBuilder nextEntry : stringBuilderList)
{
nextEntry.reverse();
}
The enhanced for-loop will go through each entry in the ArrayList, and the StringBuilder's reverse will change the order of the letters.
EDIT TO SHOW FORMATTING
ArrayList<StringBuilder> stringBuilderList= new ArrayList<>();
*note. given that this is for a lab, its probably for learning purposes and using built-in classes that does all the work for you are usually not the intended solution. -- #experiment unit 1998X
Try to use StringBuilder
And use method reverse
This is another "ArrayList and StringBuilder-less" version.
Create two Strings, one filled and one empty:
String nextString = stringArray[i],
template = new String();
Loop through the length of the String, adding the next character in from the end each time through.
int length = nextString.length() - 1;
for(int j = 0; j < length; j++)
{
template += nextString.charAt(length - j);
}
Add the whole String to the String array's index
stringArray[i] = template;
NOTE
This is an inner loop for a String array and is NOT complete code
I have a read() method and inside I want to separate the Strings(which have spaces between them) and putting them in a two dimensional array, but before that I get rid of all the spaces. After the array initialized, it is given to the CSV constructor and that is creating its own 2D array.
The problem is that I always get the following error: "variable sr might not have been initialized" at CSV csv = new CSV(sr).
How do I make sure that my array gets the valid String?
private String[][] tomb;
private CSV(String[][] t2) {
tomb = new String[t2.length][];
for(int i = 0; i < t2.length; i++) {
tomb[i] = new String[t2[i].length];
for(int j = 0; j < t2[i].length; j++) {
tomb[i][j] = t2[i][j];
}
}
}
public static CSV read(Scanner sc) {
String[][] sr;
int n = 0;
while (sc.hasNextLine())
{
String line = sc.nextLine();
String[] str = line.split(",");
sr = new String[str.length][];
for (int i = 0; i < str.length; i++) {
sr[i][n].replaceAll("\\s+","");
}
n++;
}
CSV csv = new CSV(sr);
return csv;
}
You can resolve the error by setting sr to null in the initialization:
String[][] sr = null;
If you want to make sure sr was set correctly, you can check if sr is still null after the while loop completes.
I wrote this program and have all the code that it should need. At first I was having some run-time errors, but I easily fixed those. Now it shows no visible errors, and when I run it, it does nothing.
In essence, what it should be doing is printing out a list of classes with students and id numbers, which have been merged from two files. It matches the ids of students to the ids of classes and forms them into a list. This all seems to be happening, it just isn't printing it out.
My code is below. Please let me know what you think. I have included a description at the top and markers of where I think the issue starts and ends. Also after the code there is an example of the contents of the two files.
/* This program reads in two files, one which contains a list of student names and id numbers, and another which lists class id numbers.
* Then, the data is taken into arrays which are then used in different sorts. One sorts the id numbers numerically, one sorts the students
* alphabetically, and one sorts the class names alphabetically.The id numbers of students are matched to class and both are compiled into
* a list which then prints out first the class name, then the list of students within it. All done alphabetically.
*
*/
import java.io.*;
import java.util.Scanner;
public class MergingFiles {
public static void main(String[] args) throws IOException {
String[][] studentArray = new String [1000][2];
String[][] classArray = new String[4000][2];
int count = 0;
Scanner sc = new Scanner(new File("students.txt"));
while(sc.hasNextLine()){
String studentInput = sc.nextLine();
String name = studentInput.substring(0, 30).trim();
String id = studentInput.substring(30).trim();
studentArray[count][0] = name;
studentArray[count][1] = id;
count++;
}
for(int i = 0; i < count-1; i++){ //sorts id number numerically
for(int j = 0; j < count-1-i; j++){
if(studentArray[j][1].compareTo(studentArray[j+1][1]) > 0){
String holder = studentArray[j][1];
studentArray[j][1] = studentArray[j+1][1];
studentArray[j+1][1] = holder;
}
}
}
int counter3 = 0;
Scanner sc2 = new Scanner(new File("classes.txt"));
while(sc2.hasNextLine()){
int counter2 = 0;
String classInput = sc2.nextLine();
while(classInput.charAt(counter2)!= ' '){
counter2++;
}
String className = classInput.substring(0, counter2);
while(classInput.charAt(counter2) == ' '){
counter2++;
}
String idNum = classInput.substring(counter2);
int low = 0;
int high = count - 1;
int mid = (high - low)/2 + low;
while(!idNum.equals(studentArray[mid][1])){ //binary search
if(idNum.compareTo(studentArray[mid][1]) < 0){
high = mid - 1;
}else
low = mid + 1;
mid = (high - low)/2 + low;
}
String studentName2 = studentArray[mid][1];
classArray[counter3][0] = className;
classArray[counter2][1] = studentName2;
}
//I THINK THE ISSUE STARTS HERE
for(int a = 0; a < (counter3 - 1); a++){ //sort class names alphabetically
for(int b = 0; b < counter3-1-a; b++){
if(classArray[b][0].compareTo(classArray[b+1][0]) > 0){
String holder2 = classArray[b][0];
classArray[b][0] = classArray[b+1][0];
classArray[b+1][0] = holder2;
}
}
}
for(int c = 0; c < (counter3 - 1); c++){ //sort class names alphabetically
for(int d = 0; d < counter3-1-c; d++){
if((classArray[d][0].compareTo(classArray[d+1][0])) == 0){
if(classArray[d][1].compareTo(classArray[d+1][1]) > 0){
String holder3 = classArray[d][1];
classArray[d][1] = classArray[d+1][1];
classArray[d+1][1] = holder3;
}
}
}
}
String currentClass = "";
for(int s = 0; s < counter3; s++){
if(!classArray[s][0].equals(currentClass)){
currentClass = classArray[s][0];
System.out.print(currentClass);
}
System.out.print(classArray[s][1]);
}
//THIS IS WHERE THE ISSUE ENDS
}
}
studentArray contents example (without //'s):
//Lambert, Desmond 451825335
//Johnston, Michaela 143547061
//Wells, Shirley 942366473
// Blevins, Dawson 407183976
// Roy, Benjamin 575069268
// Mitchell, Jaquan 285633099
// Freeman, Nayeli 312234364
// Benson, Myles 755491358
// Wilkinson, Stephany 384506082
// Bradshaw, Nikki 159900631
// Davila, Sarah 788743448
// Wyatt, Eddie 253830483
// Ortega, Josh 891761169
// Pruitt, Deven 533987743
// Harrison, Aliyah 710258372
// Perez, Emerson 611325979
// Stanton, Sonny 430095944
// Rice, Bruce 301915859
// Callahan, Brandon 327995163
// Torres, Jovan 629852538
// Mathis, Timothy 936191071
// Calhoun, Nathanael 107519769
// Mullen, Malik 711847273
// Sims, Marvin 519717164
// Pham, Siena 530779316
// Vincent, Demetrius 618276821
etc.
classArray contents example (without //'s):
//ECON101 938597595
//BUS100 951008337
//ECON408 620903271
//PHY101 695451867
//COSC150 392023624
//MATH215 557048539
//COSC325 495522117
//BUS215 185642398
//ECON408 807662685
//MATH215 920062540
//MATH325 517786537
//PHY150 915173832
//BUS100 518392974
//BUS408 410797598
//BUS215 152414047
//PHY150 561839967
etc.
Thanks.
I think you should add tokens in the txt file and using StringTokenizer have the columns captured per row in the arrays. Once you have all the data in the array, then you should be process the data to merge.
When you are saying "The id numbers of students are matched to class and both are compiled into a list which then prints out first the class name, then the list of students within it. All done alphabetically."
Are you intend to match the id in the student file with class file? if so, the above example values does not show it though.
Also if you have the student and classtxt files, share those and I can try running with them.
Basic problem is,counter3 is never set to anything besides 0, so the body of your print loop never executes. You probably want to increment counter3 here, and also use it as the index into classArray for both of these assignment statements (I think you're mistakenly using counter2 to set the student name):
classArray[counter3][0] = className;
classArray[counter2][1] = studentName2;
counter3++;
By the way, your sorting is broken because you're sorting the student ids without also sorting their names - make sure to shuffle the whole Student[] (studentArray[i]) forward instead of only studentArray[i][1]. Here's a working example using Arrays.sort(T[] a, Comparator<? super T> c):
// sort students by id number and sort null elements to end of array
Arrays.sort(studentArray, new Comparator<String[]>() {
public int compare(String[] student1, String[] student2)
{
if (student1[1] == null) return 1;
if (student2[1] == null) return -1;
return student1[1].compareTo(student2[1]);
}
});
I am trying to use the setCharAt method in a StringBuilder but I am getting a null pointer exception. Is there a way I can add values to the StringBuilder array I have made so I wont get these error.
From research I have found the .append() method but I'm not even sure how it works.
import java.util.*; // Allows for the input of a scanner method.
import java.io.*; // Allows for the inputting and outputting of a data file.
import java.lang.*; // Allows for the use of String Methods.
//////////////////////////////////////////////////////////////////////////////////////
public class TESTY
{
static Scanner testanswers;
static PrintWriter testresults;
public static void main(String[] args) throws IOException
{
testanswers = new Scanner(new FileReader("TestInput.dat"));
testresults = new PrintWriter("TestOutput.dat");
String StudentID;
String answers;
// Reads first two lines first to know how many records there are.
String answerKey = testanswers.nextLine();
int count = Integer.parseInt(testanswers.nextLine());
// Allocate the array for the size needed.
String[][] answerArray = new String[count][];
for (int i = 0; i < count; i++)
{
String line = testanswers.nextLine();
answerArray[i] = line.split(" ", 2);
}
for(int row = 0; row < answerArray.length; row++)
{
for(int col = 0; col < answerArray[row].length; col++)
{
System.out.print(answerArray[row][col] + " ");
}
System.out.println();
}
gradeData(answerArray, answerKey);
testanswers.close();
testresults.close();
}
///////////////////////////////////////////////////////////
//Method: gradeData
//Description: This method will grade testanswers showing
//what was missed, skipped, letter grade, and percentage.
///////////////////////////////////////////////////////////
public static double gradeData(String[][] answerArray, String answerKey)
{
String key = answerKey;
double Points = 0;
StringBuilder[] wrongAnswers = new StringBuilder[5];
String studAnswers;
for(int rowIndex = 0; rowIndex < answerArray.length; rowIndex++) /// Counting rows
{
studAnswers = answerArray[rowIndex][1].replace(" ", "S"); ///Counts rows, Col stay static index 1
for(int charIndex = 0; charIndex < studAnswers.length(); charIndex++)
{
if(studAnswers.charAt(charIndex) == key.charAt(charIndex))
{
Points += 2;
}
else if(studAnswers.charAt(charIndex) == 'S')
{
Points --;
}
else if(studAnswers.charAt(charIndex) != key.charAt(charIndex))
{
for(int i = 0; i < wrongAnswers.length; i++)
{
wrongAnswers[i].setCharAt(charIndex, 'X');
}
Points -= 2;
}
}
System.out.println(Points);
}
return Points;
}
}
The error is occurring on line 91 :
wrongAnswers[i].setCharAt(charIndex, 'X');
You have declared an array of StringBuilders, but you haven't initialized any of the slots, so they're still null.
Initialize them:
StringBuilder[] wrongAnswers = new StringBuilder[5];
for (int i = 0; i < wrongAnswers.length; i++)
{
wrongAnswers[i] = new StringBuilder();
}
Additionally, using setCharAt won't work here, because initially, there is nothing in the StringBuilder. Depending on what you want here, you may need to just call append, or you may initially want a string full of spaces so that you can set a specific character to 'X'.
StringBuilder[] wrongAnswers = new StringBuilder[5];
does not create 5 empty StringBuilders but 5 null StringBuilders.
You need to call something like
wrongAnswers[i] = new StringBuilder()
in order to initialize your 5 array members.
Your problem is that
StringBuilder[] wrongAnswers = new StringBuilder[5];
does not create 5 StringBuilder objects. It only creates an array with 5 null StringBuilder references. You need to create each StringBuilder separately with a line such as
wrongAnswers[i] = new StringBuilder();
inside a loop over i.
Well I have been stumped as to the best way to do this, I have written the code to read in lines of code from txt files as List. I can then print specific parts or convert this to an array of objects. But, ultimately I would like to have just a 2d int array you can see often in C/C++. I am very green when it comes to java, having only started earlier this week. I have like it up until this point of making dynamic 2d arrays at run time. Can any of you suggest a good way to get to a 2d int array from where i am currently stuck. I was just about to convert it to a char array using 'toChar', then to take the (value#index-48) and store it in its corresponding spot, but that seems pretty ghetto to me.
====updated==========================
eh, thanks for all the replies, but I just figured out how to do it using doubles, so for anyone else, here you go. I would still rather have int, since I have already built my other matrixops classes using this type, but Double shouldn't be an issue i guess.
package uaa.cse215;
import java.io.*;
import java.util.*;
public class ReadMatrix {
private Double[][] A;
private Double[][] B;
private int count;
public int filedir(String matrix) throws Exception{
Double[][] Temp;
String[] arr;
BufferedReader rd = new BufferedReader(new FileReader(matrix));
String s;
List<String> textFile = new ArrayList<String>();
while ((s=rd.readLine())!=null) {
textFile.add(s);
}
String splitarray[] = textFile.get(0).split(" ");//run once to grab # cols
int rows = textFile.size();//number of rows
int cols = splitarray.length;//number of cols
Temp = new Double[rows][cols]; // now can initiate array
for (int i=0; i<rows; i++) {
s = textFile.get(i);
arr = s.split(" ");
for (int j=0; j<cols; j++) {
Temp[i][j] = Double.parseDouble(arr[j]);
}
}
count++;
if (count == 1){
A = Temp;
}
else
B = Temp;
rd.close();
return(1);
}
}
Please note that Java has the char data type which is a 16bit unsigned integer holding a UTF-16 code point. int is in Java always a signed 32 bit integer. So if you want a C like Arrays of chars representing the content of a String, you should use a char[][]
To convert the content of your List<String> into a 2d array you can use the following code:
char[][] twoDarray = new char[textFile.size()];
for(int i = 0; i < textFile.size(); i+)
{
twoDarray[i] = textFile.get(i).toCharArray();
}
The array twoDarray then contains all Strings each as a char array.
This line won't compile
splitarray[j] = textFile.get(i).split(" ");
as splitarray[j] is of type String and split returns an array of Strings
Do the following instead:
for(int row=0;row<textFile.size();row++){
String[] splitarray = textFile.get(row).split(" ");
for(int col=0;col<splitarray.length;col++){
tmp[row][col] = Integer.parse(splitarray[col]);
}
}
if the input matrix dimentions are dynamic or jagged you can use
List<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
to read numbers and than copy it to raw 2d array if you want.
java.util.Scanner has many handy methods for reading "typed" data from input
Here's an example reading file to 2D array
public static int[][] read2DArray(String fileName) throws FileNotFoundException {
Scanner sc = null;
List<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
int columnCount = 0;
int[][] arr = null;
try {
sc = new Scanner(new File(fileName));
while (sc.hasNextLine()) {
// Read line
String line = sc.nextLine();
// Split it
String[] nums = line.split(" ");
if (nums.length > columnCount) {
columnCount = nums.length;
}
// Convert to integers and add to list
list.add(new ArrayList<Integer>());
for (String n : nums) {
list.get(list.size() - 1).add(new Integer(n));
}
}
// Convert list to array
int rowCount = list.size();
arr = new int[rowCount][columnCount];
for (int i = 0; i < rowCount; i++) {
for (int j = 0; j < list.get(i).size(); j++) {
arr[i][j] = list.get(i).get(j);
}
}
} finally {
if (sc != null) {
sc.close();
}
}
return arr;
}
Assuming your data file contains ascii-represented numbers that you want parsed into integers:
11 -9 13
12 55 102
1 1 1024
Then you can use the Integer(String s) constructor to parse your string objects.
Also, I suggest splitting each row only once. It won't matter much for small arrays, but the larger your inputs get, the more you'll needlessly recompute the splits.
An (untested) re-writing:
int tmp[][] = new int [rows][cols];
for(int i=0;i<rows;i++){
splitarray = textFile.get(i).split(" ");
for(int j=0;j<cols;j++){
tmp[i][j] = Integer(splitarray[j]);
}
}