Make a method that creates an array with given parameters? - java

So I have several arrays that I create with large CSVs with some basic code - no issues there. But I want to be able to make a new array from a CSV with a method instead of just copying and pasting code. Here's basically what I want to do.
public static void makeArray(String name, String path, int rows, int columns){
//get CSV from path and make array with that data
}
But here's what I currently have, and it doesn't work.
static String[][] makeArray(String name, String path, int rows, int columns) {
name = new String[rows][columns];
Scanner scanIn = null;
int r = 0;
String inputLine = "";
try {
System.out.println("Setting up " + name);
scanIn = new Scanner(new BufferedReader(new FileReader(path)));
while (scanIn.hasNextLine()) {
inputLine = scanIn.nextLine();
String[] inArray = inputLine.split(",");
for(int x = 0; x < inArray.length; x++) {
name[r][x] = inArray[x];
}
r++;
}
return name;
} catch(Exception e){
System.out.println(e);
}
}
I appreciate the help!!

Your code has the following issues:
Java is pass-by-value, so remove the name parameter and return the newly created array instead.
Don't ignore exceptions. If you don't want callers to have to process the IOException, catch it and send an unchecked exception.
Use try-with-resources to make sure your Reader is closed correctly.
Don't pre-declare variables. Declare them where used.
Applying fixes for the above issue, your code becomes:
static String[][] makeArray(String path, int rows, int columns) {
String[][] name = new String[rows][columns];
try (Scanner scanIn = new Scanner(new BufferedReader(new FileReader(path)))) {
for (int r = 0; scanIn.hasNextLine(); r++) {
String inputLine = scanIn.nextLine();
String[] inArray = inputLine.split(",");
for (int x = 0; x < inArray.length; x++) {
name[r][x] = inArray[x];
}
}
} catch (IOException e) {
throw new IllegalArgumentException("Error reading file '" + path + "': " + e, e);
}
return name;
}
Be aware that the code will fail if the file contains too many lines, or if a line contains too many values. You might want to check for that, or make the code figure out the number of rows by itself, e.g. using a List.
UPDATE
To auto-create an array with the number of rows actually found in the file, you can use the following code.
The code also uses the Arrays.copyOf() method to make sure every row is the given number of columns. If a line in the file contains more values than that, they are silently discarded.
static String[][] makeArray(String path, int columns) {
List<String[]> rows = new ArrayList<>();
try (Scanner in = new Scanner(new BufferedReader(new FileReader(path)))) {
while (in.hasNextLine()) {
String[] values = in.nextLine().split(",");
rows.add(Arrays.copyOf(values, columns)); // ignores excessive values
}
} catch (IOException e) {
throw new IllegalArgumentException("Error reading file '" + path + "': " + e, e);
}
return rows.toArray(new String[rows.size()][]);
}

Make a method that creates an array with given parameters?
The problem with your code is that you are not returning anything in your method due to void keyword and the fact that you didn't use return keyword.
So here's what you need to do:
First its return type should be String[][].
Second you should return the edited array in the end of your method.
Another thing is that you are trying to assign a `String[]
name = new String[rows][columns];
Which will cause the Error cannot convert String[][] to String.
So in your method definition change the type of name to String[][] name or even better declare it inside the method because you are initializing it in the method.

Related

Printing out array data stored from File read

I'm trying to create a class that uses a separate method to read and store two sets of data from a file into 2 different arrays. I don't know if it's the read method or my output that is incorrect but I can't seem to figure out how to have it printout all data sets. I get the last line of the file instead of all content.
examples from products.txt are
Product1,1100
Product2,1205
Product3,1000
Main Method
String[] pName;
double[] pPrice;
String outputStr = null;
int i = 0;
//String name = null;
// Input number of customers
//initialize arrays with size
pPrice=new double[50];
pName=new String[50];
// read from file, the method is incomplete
try {
readFromFile(pName, pPrice, "products.txt");
} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(null, "File cannot be read");
e.printStackTrace();
}
for (i = 0; i < pName.length; i++) {
outputStr = pName[i] + "," + pPrice[i] + "\n";
}
// Call method before sorting both arrays
display(outputStr);
Reading Method
public static void readFromFile(String[] pName, double[] pPrice, String fileName) throws FileNotFoundException {
// read data from products
// Create a File instance
File file = new File(fileName);
// Create a Scanner for the file
Scanner sc = new Scanner(file);
// Read data from a file, the data fields are separated by ','
// Change the Scanner default delimiter to ','
sc.useDelimiter(",|\r\n");
// Start reading data from file using while loop
int i = 0;
while (sc.hasNext()) {
String name = sc.next();
String cost = sc.next();
//add the customer data through arrays
pName[i] = name;
pPrice[i] = Double.parseDouble(cost);
i++;
}//end while
// Close the file
The problem is that your for loop assigns every line to the outputStr variable:
for (i = 0; i < pName.length; i++) {
outputStr = pName[i] + "," + pPrice[i] + "\n";
}
Seeing your linefeed in the end I assume you want to concatenate all lines into that string variable. So change that code into
for (i = 0; i < pName.length; i++) {
outputStr += pName[i] + "," + pPrice[i] + "\n";
}
As you initialize the variable to be null this may throw a NullPointerException. If that is the case, simply initialize with "".

Is it possible to write a text file in such a way that when read by the Java compiler, it will add a line break at certain points?

For my Java class, I'm working on a project that is essentially a database for MTG cards. I have to read from a file as part of the project, so I am reading the card information from a file, and then splitting the lines to put each different type of information together to form different object classes for the different types of cards. The main nitpicky issue I'm running into right now is that I need the card text to be on one line in the text file so I can read it line by line, but I'd prefer if it weren't all on one line when I print it to the console. Is there any way to add a character combination into the text of the file itself that will tell my compiler, "line break here," when it reads that, or am I out of luck? I know I could just use \n in the code to achieve this, but as I am looping through the file, there is no way to do so properly that I know of, as not every card's text needs line breaks inserted. If it matters, this is the chunk of my code that deals with that:
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Scanner;
public class MTG {
public static void main(String[] args) {
int creatureLength = 4;
//Prompt User
Scanner sc = new Scanner(System.in);
System.out.println("Welcome to the Magic: the Gathering card database. This tool currently supports Rare and Mythic Rare cards from the Throne of Eldraine Expansion.");
try {
System.out.println("\nSelect the card type you'd like to view.");
System.out.println(""
+ "(1)Creatures\n"
);
int choice = Integer.parseInt(sc.next());
//Choose type
//Creatures
if(choice == 1){
Creature[] creatures = creatureGen("textfiles/Creatures.txt", creatureLength);
System.out.println("\nViewing creatures. Which card would you like to view?: \n");
for(int k = 0; k < creatureLength; k++) {
System.out.println(
"(" + (k + 1) + ") " + creatures[k].getName());
}
int creatureChoice = Integer.parseInt(sc.next());
try {
System.out.println("\n" + creatures[(creatureChoice - 1)]);}
catch(Exception e) {
System.out.println("Input was not a specified number. Exiting...");
}
}
}
catch(NumberFormatException ex){
System.out.println("Input was not a specified number. Exiting...");
}
sc.close();
}
//Read Creature text file
public static Creature[] creatureGen(String path, int length) {
Creature[] creatures = new Creature[length];
try {
FileReader file = new FileReader(path);
BufferedReader reader = new BufferedReader(file);
String name[] = new String[length];
String cost[] = new String[length];
String color[] = new String[length];
String type[] = new String[length];
String cTypes[] = new String[length];
String tags[] = new String[length];
String text[] = new String[length];
int power[] = new int[length];
int toughness[] = new int[length];
for (int i = 0; i < length; i++) {
String line = reader.readLine();
if(line != null) {
name[i] = line.split("\\|")[0];
cost[i] = line.split("\\|")[1];
color[i] = line.split("\\|")[2];
type[i] = line.split("\\|")[3];
cTypes[i] = line.split("\\|")[4];
tags[i] = line.split("\\|")[5];
text[i] = line.split("\\|")[6];
power[i] = Integer.parseInt(line.split("\\|")[7]);
toughness[i] = Integer.parseInt(line.split("\\|")[8]);
creatures[i] = new Creature(name[i], cost[i], color[i], type[i], cTypes[i], tags[i], text[i], power[i], toughness[i]);
}
}
reader.close();
}
catch (Exception e) {
System.out.println("Error reading file: " + path);
}
return creatures;
}
}
The Creature object class essentially just stores the data that I am putting into it with the creatureGen method. A sample line from the text file I am reading from looks something like this:
Charming Prince|1W|White|Creature|Human Noble||When Charming Prince enters the battlefield, choose one — • Scry 2. • You gain 3 life. • Exile another target creature you own. Return it to the battlefield under your control at the beginning of the next end step.|2|2
It would be ideal to be able to insert line breaks after each of the bullet points in this card, for example, but as I said earlier, I need the text to be in one line for my loop to read it. Is there any way around this when I print this back to the console? I appreciate any help.
Just replace those bullet points with line breaks :
text[i] = line.split("\\|")[6].replaceAll("•","\n");
Also, you should not split each time you need an element, put the result of line.split("\|") in a String[] variable and use it afterwards.
for (int i = 0; i < length; i++) {
String line = reader.readLine();
if(line != null) {
String[] elements = line.split("\\|");
name[i] = elements[0];
cost[i] = elements[1];
color[i] = elements[2];
type[i] = elements3];
cTypes[i] = elements[4];
tags[i] = elements[5];
text[i] = elements[6].replaceAll("•","\n");
power[i] = Integer.parseInt(elements[7]);
toughness[i] = Integer.parseInt(elements[8]);
creatures[i] = new Creature(name[i], cost[i], color[i], type[i], cTypes[i], tags[i], text[i], power[i], toughness[i]);
}
}
Finally, about vocabulary, the compiler is not reading your file. The compiler translates your code into binary instructions for the processor (to summarize).
Your file is read at runtime.

Trying to split array list of strings get warning #NonNull String regex Android Studio Java

I am trying to load a file from a previously saved values from an editText. On the next load I am trying to make the fields populated with the previously entered data using split to get everything on that line after the split, as seen in this picture. For some reason every time I try and split with .split("Name") everything between the quotation marks goes black instead of green and I get that #NonNull.
public void loadList(){
loadText = new ArrayList<String>();
Context context = getApplicationContext();
File file = new File (path + "/personalProfile.txt");
try{
editText_name.setText("");
editText_dob.setText("");
editText_mobile.setText("");
editText_journal.setText("");
editText_medical.setText("");
String line = "";
FileInputStream fis = new FileInputStream(file);
BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
while((line = reader.readLine()) != null)
{
loadText.add(line);
}public void loadList(){
String loadedText = String.valueOf(loadText.get(0));
String rname = "Hello: Name";
String helloName [] = rname.split("Hello: ");
//String nameToText [] = loadedText.split("");
for(int i = 0; i < loadText.size(); i++){
editText_name.setText(String.valueOf(loadText.get(0).split("Name:")));
}
//set all the editText values accordingly
}catch (Exception e){
System.out.println("Error " + e);
}
}
There is no string you have entered that would satisfy "Name: " in
"Hello: Name"
And I think what you want in your for loop is not element 0 all the time for your arraylist, it should be:
for (int i = 0; i < loadText.size(); i++){
editText_name.setText(String.valueOf(loadText.get(i).split("Hello: ")));
}
But the more correct way would be:
for (int i = 0; i < loadText.size(); i++){
editText_name.setText(String.valueOf(loadText.get(i).replace("Hello: ")));
}
If you just wanted the name.
However I think the problem with not retrieving the values is you have to add:
#Override
public void onSaveInstanceState(Bundle out) {
out.putStringArrayList("loadValues", loadValues);
}
and to retrieve them:
#Override
public void onRestoreInstanceState(Bundle in) {
loadValues = in.getStringArrayList("loadValues");
//call method to set values again
}

JAVA read text files, count numbers and write it to Jtable [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am still learning JAVA and have been trying to find a solution for my program for a few days, but I haven't gotten it fixed yet.
I have many text files (my program saves). The files look like this:
text (tab) number (tab) number (tab)...
text (tab) number (tab) number (tab)...
(tab) means that there is tabulation mark,
text means that is text (string),
number means that there is number (integer).
number of files can be from 1 up to 32 and file with names like: january1; january2; january3...
I need to read all of those files (ignore strings) and sum only numbers like so:
while ((line = br.readLine()) != null) {
counter=counter+1;
String[] info = line.split("\\s+");
for(int j = 2; j < 8; j++) {
int num = Integer.parseInt(info[j]);
data[j][counter]=data[j][counter]+num;
}
};
Simply I want sum all that "tables" to array of arrays (or to any similar kind of variable) and then display it as table. If someone knows any solution or can link any similar calculation, that would be awesome!
So, as I see it, you have four questions you need answered, this goes against the site etiquette of asking A question, but will give it a shot
How to list a series of files, presumably using some kind of filter
How to read a file and process the data in some meaningful way
How to manage the data in data structure
Show the data in a JTable.
Listing files
Probably the simplest way to list files is to use File#list and pass a FileFilter which meets your needs
File[] files = new File(".").listFiles(new FileFilter() {
#Override
public boolean accept(File pathname) {
return pathname.getName().toLowerCase().startsWith("janurary");
}
});
Now, I'd write a method which took a File object representing the directory you want to list and a FileFilter to use to search it...
public File[] listFiles(File dir, FileFilter filter) throws IOException {
if (dir.exists()) {
if (dir.isDirectory()) {
return dir.listFiles(filter);
} else {
throw new IOException(dir + " is not a valid directory");
}
} else {
throw new IOException(dir + " does not exist");
}
}
This way you could search for a number of different set of files based on different FileFilters.
Of course, you could also use the newer Paths/Files API to find files as well
Reading files...
Reading multiple files comes down to the same thing, reading a single file...
// BufferedReader has a nice readline method which makes
// it easier to read text with. You could use a Scanner
// but I prefer BufferedReader, but that's me...
try (BufferedReader br = new BufferedReader(new FileReader(new File("...")))) {
String line = null;
// Read each line
while ((line = br.readLine()) != null) {
// Split the line into individual parts, on the <tab> character
String parts[] = line.split("\t");
int sum = 0;
// Staring from the first number, sum the line...
for (int index = 1; index < parts.length; index++) {
sum += Integer.parseInt(parts[index].trim());
}
// Store the key/value pairs together some how
}
}
Now, we need some way to store the results of the calculations...
Have a look at Basic I/O for more details
Managing the data
Now, there are any number of ways you could do this, but since the amount of data is variable, you want a data structure that can grow dynamically.
My first thought would be to use a Map, but this assumes you want to combining rows with the same name, otherwise you should just us a List within a List, where the outer List represents the rows and the Inner list represents the column values...
Map<String, Integer> data = new HashMap<>(25);
File[] files = listFiles(someDir, januraryFilter);
for (File file : files {
readFile(file, data);
}
Where readFile is basically the code from before
protected void readData(File file, Map<String, Integer> data) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line = null;
// Read each line
while ((line = br.readLine()) != null) {
//...
// Store the key/value pairs together some how
String name = parts[0];
if (data.containsKey(name)) {
int previous = data.get(name);
sum += previous;
}
data.put(name, sum);
}
}
}
Have a look at the Collections Trail for more details
Showing the data
And finally, we need to show the data. You could simply use a DefaultTableModel, but you already have the data in structure, why not re-use it with a custom TableModel
public class SummaryTableModel extends AbstractTableModel {
private Map<String, Integer> data;
private List<String> keyMap;
public SummaryTableModel(Map<String, Integer> data) {
this.data = new HashMap<>(data);
keyMap = new ArrayList<>(data.keySet());
}
#Override
public int getRowCount() {
return data.size();
}
#Override
public int getColumnCount() {
return 2;
}
#Override
public Class<?> getColumnClass(int columnIndex) {
Class type = Object.class;
switch (columnIndex) {
case 0:
type = String.class;
break;
case 1:
type = Integer.class;
break;
}
return type;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Object value = null;
switch (columnIndex) {
case 0:
value = keyMap.get(rowIndex);
break;
case 1:
String key = keyMap.get(rowIndex);
value = data.get(key);
break;
}
return value;
}
}
Then you would simply apply it to a JTable...
add(new JScrollPane(new JTable(new SummaryTableModel(data)));
Take a look at How to Use Tables for more details
Conclusion
There are a lot of assumptions that have to be made which are missing from the context of the question; does the order of the files matter? Do you care about duplicate entries?
So it becomes near impossible to provide a single "answer" which will solve all of your problems
I took all the january1 january2... files from the location and used your same function to calculate the value to be stored.
Then I created a table with two headers, Day and Number. Then just added rows according to the values generated.
DefaultTableModel model = new DefaultTableModel();
JTable table = new JTable(model);
String line;
model.addColumn("Day");
model.addColumn("Number");
BufferedReader br = null;
model.addRow(new Object[]{"a","b"});
for(int i = 1; i < 32; i++)
{
try {
String sCurrentLine;
String filename = "january"+i;
br = new BufferedReader(new FileReader("C:\\january"+i+".txt"));
int counter = 0;
while ((sCurrentLine = br.readLine()) != null) {
counter=counter+1;
String[] info = sCurrentLine.split("\\s+");
int sum = 0;
for(int j = 2; j < 8; j++) {
int num = Integer.parseInt(info[j]);
sum += num;
}
model.addRow(new Object[]{filename, sum+""});
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null)br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
JFrame f = new JFrame();
f.setSize(300, 300);
f.add(new JScrollPane(table));
f.setVisible(true);
Use Labled Loop and Try-Catch. Below piece adds all number in a line.
You could get some hint from here:
String line = "text 1 2 3 4 del";
String splitLine[] = line.split("\t");
int sumLine = 0;
int i = 0;
contSum: for (; i < splitLine.length; i++) {
try {
sumLine += Integer.parseInt(splitLine[i]);
} catch (Exception e) {
continue contSum;
}
}
System.out.println(sumLine);
Here is another example using vectors . in this example directories will be searched for ".txt" files and added to the JTable.
The doIt method will take in the folder where your text files are located.
this will then with recursion, look for files in folders.
each file found will be split and added following you example file.
public class FileFolderReader
{
private Vector<Vector> rows = new Vector<Vector>();
public static void main(String[] args)
{
FileFolderReader fileFolderReader = new FileFolderReader();
fileFolderReader.doIt("D:\\folderoffiles");
}
private void doIt(String path)
{
System.out.println(findFile(new File(path)) + " in total");
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Vector<String> columnNames = new Vector<String>();
columnNames.addElement("File Name");
columnNames.addElement("Size");
JTable table = new JTable(rows, columnNames);
JScrollPane scrollPane = new JScrollPane(table);
frame.add(scrollPane, BorderLayout.CENTER);
frame.setSize(300, 150);
frame.setVisible(true);
}
private int findFile(File file)
{
int totalPerFile = 0;
int total = 0;
File[] list = file.listFiles(new FilenameFilter()
{
public boolean accept(File dir, String fileName)
{
return fileName.endsWith(".txt");
}
});
if (list != null)
for (File textFile : list)
{
if (textFile.isDirectory())
{
total = findFile(textFile);
}
else
{
totalPerFile = scanFile(textFile);
System.out.println(totalPerFile + " in " + textFile.getName());
Vector<String> rowItem = new Vector<String>();
rowItem.addElement(textFile.getName());
rowItem.addElement(Integer.toString(totalPerFile));
rows.addElement(rowItem);
total = total + totalPerFile;
}
}
return total;
}
public int scanFile(File file)
{
int sum = 0;
Scanner scanner = null;
try
{
scanner = new Scanner(file);
while (scanner.hasNextLine())
{
String line = scanner.nextLine();
String[] info = line.split("\\s+");
int count = 1;
for (String stingInt : info)
{
if (count != 1)
{
sum = sum + Integer.parseInt(stingInt);
}
count++;
}
}
scanner.close();
}
catch (FileNotFoundException e)
{
// you will need to handle this
// don't do this !
e.printStackTrace();
}
return sum;
}
}

Write JTable Contents to Text File While Keeping its Format In Java

I have a Jtable which displays the following when triggered.
How can I write all the contents of it to a Text File while keeping its original format. The Text File should look something like this.
Line Number Error Solution Percentage(%)
6 in int 33%
This is what I tried so far. But only value 6 is being written to the file. Any Help.
My codes(only the main parts):
private static final String[] columnNames = {"Line Number", "Error","Solution","Percentage (%)"};
static DefaultTableModel model = new DefaultTableModel(null,columnNames);
public static void DisplayMyJList(List<CaptureErrors> x) throws IOException
{
String [] myErrorDetails = new String[x.size()];
int i = 0;
int line,percentage;
String err, sol;
String aLine;
StringBuffer fileContent = new StringBuffer();
for(CaptureErrors e: x)
{
Vector row = new Vector();
row.add(e.getLinenumber());
row.add(e.getMyfounderror());
row.add(e.getMycorrection());
row.add(e.getMyPercentage()+"%");
model.addRow( row );
for (int i1 = 0; i1 < model.getRowCount(); i1++) {
Object cellValue = model.getValueAt(i1, 0);
// ... continue to read each cell in a row
fileContent.append(cellValue);
// ... continue to append each cell value
FileWriter fileWriter = new FileWriter(new File("C:\\Users\\Antish\\Desktop\\data.txt"));
fileWriter.write(fileContent.toString());
fileWriter.flush();
fileWriter.close();
}
Update I tried this with 2 loops and it gives me the following. I lost the original Format:
Code:
String separator = System.getProperty( "line.separator" );
try
{
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file,true));
PrintWriter fileWriter = new PrintWriter(bufferedWriter);
for(int i1=0; i1<model.getRowCount(); ++i1)
{
for(int j=0; j<model.getColumnCount(); ++j)
{ String names = columnNames[counter];
String s = model.getValueAt(i1,j).toString();
fileWriter.print(names +" ");
fileWriter.append( separator );
fileWriter.print(s + " ");
counter ++;
}
fileWriter.println("");
}
fileWriter.close();
}catch(Exception e)
{
Your code isn't complete but I can see 1, maybe 2 errors:
1) You need a double loop, one for the rows and then a second for every column in the row. The code you posted only shows you getting the value from the first column which would explain why you only see "6".
2) The code to write to the file needs to be outside your two loops. The way the code is written now you will recreate a new file for every row, which mean you will only ever have a single row of data in the file

Categories