I have JTable where I show data from text file:
Now, for deleting I have method like this:
private void delete(ActionEvent evt) {
DefaultTableModel model = (DefaultTableModel) tblRooms.getModel();
// get selected row index
try {
int SelectedRowIndex = tblRooms.getSelectedRow();
model.removeRow(SelectedRowIndex);
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex);
}
}
And action listener:
btnDelete.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
delete(e);
}
});
It will delete row in JTable and thats okey, but my text file have 7 splits, where last spit is for logical deleting. So, if false - room isn't deleted.
13|family room|name apartman|4|true|true|true|false
14|superior room|super room|2|true|false|false|false
15|room|room for one|1|false|false|true|false
0|MisteryRoom|Mistery|0|true|true|free|false
How to delete certain room from JTable on correct way, and change from false to true?
For example if I click on super room, how to delete exactly that room.
This sort of thing is best handled using a database rather than a text file for a great number of reasons, never the less since you are utilizing a text file as your data storage I will demonstrate one way to replace a value (substring) in a specific data text file line.
Now, the following method can be used to modify any piece of field data on any file data line...even the room number so keep that in mind. You will need to ensure that you only modify when it's best to do so:
/**
* Updates the supplied Room Number data within a data text file. Even the
* Room Number can be modified.
*
* #param filePath (String) The full path and file name of the Data File.
*
* #param roomNumber (Integer - int) The room number to modify data for.
*
* #param fieldToModify (Integer - int) The field number in the data line to
* apply a new value to. The value supplied here is to be considered 0 based
* meaning that 0 actually means column 1 (room number) within the file data
* line. A value of 7 would be considered column 8 (the deleted flag).
*
* #param newFieldValue (String) Since the file is string based any new field
* value should be supplied as String. So to apply a boolean true you will need
* to supply "true" (in quotation marks) and to supply a new room number that
* room number must be supplied a String (ie: "666").
*
* #return (Boolean) True if successful and false if not.
*/
public boolean updateRoomDataInFile(String filePath, int roomNumber,
int fieldToModify, String newFieldValue) {
// Try with resources so as to auto close the BufferedReader.
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
// Add the data file contents to a List interface...
List<String> dataList = new ArrayList<>();
while ((line = reader.readLine()) != null) {
dataList.add(line);
}
for (int i = 0; i < dataList.size(); i++) {
line = dataList.get(i).trim(); // Trim off any leading or trailing whitespaces (if any).
// Skip Blank lines (if any) and skip Comment lines (if any).
// In this example file comment lines start with a semicolon.
if (line.equals("") || line.startsWith(";")) {
continue;
}
//Split each read line so as to collect the desired room number
// since everything will always be based from this unique ID number.
// Split is done baesed on the Pipe (|) character since this is
// what is implied with your data example.
String[] roomData = line.split("\\|");
// Get the current file data line room number.
// Make sure the first piece of data is indeed a valid integer room
// number. We use the String.matches() method for this along with a
// regular expression.
if (!roomData[0].trim().matches("\\d+")) {
// If not then inform User and move on.
JOptionPane.showMessageDialog(null, "Invalid room number detected on file line: "
+ (i + 1), "Invalid Room Number", JOptionPane.WARNING_MESSAGE);
continue;
}
// Convert the current data line room number to Integer
int roomNum = Integer.parseInt(roomData[0]);
// Does the current data line room number equal the supplied
// room number?
if (roomNum != roomNumber) {
// If not then move on...
continue;
}
// If we reach this point then we know that we are currently on
// the the data line we need and want to make changes to.
String strg = ""; // Use for building a modified data line.
// Iterate through the current data line fields
for (int j = 0; j < roomData.length; j++) {
// If we reach the supplied field number to modify
// then we apply that modification to the field.
if (j == fieldToModify) {
roomData[j] = newFieldValue;
}
// Build the new data line. We use a Ternary Operator, it is
// basicaly the same as using a IF/ELSE.
strg += strg.equals("") ? roomData[j] : "|" + roomData[j];
}
// Replace the current List element with the modified data.
dataList.set(i, strg);
}
// Rewrite the Data File.
// Try with resources so as to auto close the FileWriter.
try (FileWriter writer = new FileWriter(filePath)) {
// Iterate through the List and write it to the data file.
// This ultimately overwrites the data file.
for (int i = 0; i < dataList.size(); i++) {
writer.write(dataList.get(i) + System.lineSeparator());
}
}
// Since no exceptions have been caught at this point return true
// for success.
return true;
}
catch (FileNotFoundException ex) {
Logger.getLogger("updateFileRoomStatus()").log(Level.SEVERE, null, ex);
}
catch (IOException ex) {
Logger.getLogger("updateFileRoomStatus()").log(Level.SEVERE, null, ex);
}
// We must of hit an exception if we got
// here so return false for failure.
return false;
}
To use this method you might want to do it this way:
private void delete() {
DefaultTableModel model = (DefaultTableModel) tblRooms.getModel();
try {
// get selected row index
int SelectedRowIndex = tblRooms.getSelectedRow();
// Get out if nothing was selected but the button was.
if (SelectedRowIndex == -1) { return; }
int roomNumber = Integer.parseInt(model.getValueAt(SelectedRowIndex, 0).toString());
updateRoomDataInFile("HotelRoomsData.txt", roomNumber, 7, "true");
model.removeRow(SelectedRowIndex);
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex);
}
In the code above a data file name of "HotelRoomsData.txt" was supplied. This of course assumes the the data file contains that name and that is is located within the root folder (directory) of your particular project. If the file is named differently and it is located in some completely different location then you will need to change this to the full path and file name of the data file, for example:
"C:/Users/Documents/MyDataFile.txt"
The code really isn't that long, it's just that there are a lot of comments accompanying it so as to explain things. Of course these comments can be deleted from the code.
Related
I need your help, I am new in Java
I need to read a flat file with 5 different of records
the way to differentiate each record is the first characters, after that I have the idea to move to an 5 different array to play with with the data inside.
example
120220502Name Last Name1298843984 $1.50
120220501other client 8989899889 $23.89
2Toronto372 Yorkland drive 1 year Ontario
512345678Transfer Stove Pay
522457839Pending Microwave Interactive
any help will quite appreciated
Break the problem into chunks. The first problem is reading the file:
try (BufferedReader reader = new BufferedReader(new FileReader("path/to/file"))) {
parseData(reader); //method to do the work.
} catch (IOException e) {
e.printStackTrace();
}
Then you need to decide what kind of record it is:
public void parseData(BufferedReader input) throws IOException {
for (String line = input.readLine(); line != null; line = input.readLine()) {
if (line.startsWith("1")) {
parseType1(line);
} else if (line.startsWith("2")) {
parseType2(line);
} else if (line.startsWith("5")) {
parseType5(line);
} else {
throw new Exception("Unknown record type: " + line.charAt(0));
}
}
}
Then you'll need to create the various parseTypeX method to handle turning the text into usable chunks and then into classes.
public Type1Record parseType1(String data) {
//create a Type1Record
Type1Record record = new Type1Record();
//split the string something like
String [] fields = data.split("\\s+");
//Assign those chunks to the record
record.setId(fields[0]);
record.setFirstName(fields[1]);
record.setLastName(fields[2]);
record.setTotal(fields[3]); //if you want this to be a real number, you'll need to remove the $
}
Repeat the process with the other record types. You'll likely need to group records together, but that should be easy enough.
I'm trying to create a csv file where only 1 team name is shown per row, so when you click the button twice it will only add the team name if its not already there. currently it adds the team "UWE" every single time you press the button. the code for this is below:
public void showStats(ActionEvent event){
try {
File matchFile = new File("src/sample/matchData.csv");
File scoreFile = new File("src/sample/scoreData.csv");
Scanner matchReader = new Scanner(matchFile);
Scanner scoreReader = new Scanner(scoreFile);
while (matchReader.hasNextLine()) {
String data = matchReader.nextLine();
List<String> matchList = Arrays.asList(data.split(","));
while (scoreReader.hasNextLine()) {
String dataScore = scoreReader.nextLine();
List<String> dataScoreList = Arrays.asList(dataScore.split(","));
if (dataScoreList.get(0).equals(matchList.get(0))) {
//
} else {
writeExcel("scoreData", matchList.get(0)) ;
}
System.out.println(dataScoreList);
}
System.out.println(matchList);
}
matchReader.close();
scoreReader.close();
} catch (FileNotFoundException e) {
System.out.println("An error occurred.");
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
The csv file "matchData" contains:
UWE,KCC,Jin,Julia,Chris,Ryan,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,5,0
The csv file "scoreData" has one empty line in it
You can first go through your source CSV file and put in a map only the lines that contain unique team key....
while (matchReader.hasNextLine()) {
String data = matchReader.nextLine();
String[] record = data.split(",", 2);
Map<String, String> matchList = new TreeMap<>();
matchList.putIfAbsent(record[0], record[1]); // only unique keys are entered.
}
// TODO write to Excel each entry in the map (you don't need to check for unique keys)
Notice that writing to Excel is done after the map is complete. This is the best approach; or at least better than what you showed in your original post. With this approach, you are letting the data structure simplify your process (and no nested loops).
UPDATE:
I forgot to mention that matchList.putIfAbsent(K, V) works with Java 8 and later. If using Java 7 or older (should upgrade Java ASAP), then you will have to do the following:
String value = matchList.get(record[0]);
if (value == null) {
matchList.put(record[0], record[1]);
}
This is because Map#get(K) returns null is no entry is found OR the map allowed for null values to be entered for a given key. Otherwise, it will return the previous value. The new method introduced in Java 8 does this check automatically.
I am reading from a URL = https://www.cia.gov/library/publications/the-world-factbook/rankorder/rawdata_2151.txt
I am trying to print out the top 3 countries but whenever I try it gives
me the total number of countries instead. Would a subString or Trim method work here? Just need a hint into the write direction. Thanks
class ButtonTotalListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
if(event.getSource()==printButton){
String line = "";
try{
String address = "https://www.cia.gov/library/publications/the-world-factbook/rankorder/rawdata_2151.txt";
URL pageLocation = new URL(address);
Scanner in = new Scanner(pageLocation.openStream());
while(in.hasNextLine()){
line = in.nextLine();
String [] lineContent = line.split("\\s{2,}");
System.out.println(Arrays.toString(lineContent));
countries.setForeground(Color.YELLOW);
countries.setText(lineContent[2]);
}
}
catch (MalformedURLException ex) {
countries.setText("Country Not Found!");
}
catch (IOException ex) {}
}
You loop over all countries in in.hasNextLine()
You should introduce a counter variable and insert a break; after your limit was reached, or change the loop condition.
Additionally check which column you want to return. It seems you return the number from thrid column (which is [2]), but if you want to use the country name you need [1] for 2nd column (array index is 0-based).
As a third, what do you do with countries? You set the text, but for each loop iteration, you overwrite the former countries text (countries is the same variable, in each iteration)
I am making a Sudoku game and I have an issue with opening a saved Sudoku file. Let's say I am doing the puzzle, and want to come back to it later, I save the partially completed puzzle to a file, which works. When I go to open it, it does not work.
Here is the code for save (both variables ROWS and COLUMNS are equal to 9):
private void savePuzzle() throws IOException {
JFileChooser fileChooser = new JFileChooser();
int returnVal = fileChooser.showDialog(this, "Save");
BufferedWriter saveFile = null;
File file;
// If the user has canceled, no need to continue
if (returnVal != JFileChooser.APPROVE_OPTION) {
return;
}
file = fileChooser.getSelectedFile();
saveFile = new BufferedWriter(new FileWriter(file));
for (int r = 0; r < ROWS; r++) {
for (int c = 0; c < COLUMNS; c++) {
saveFile.write(inputBoxes[r][c].getText());
if (c < ROWS - 1) {
saveFile.write(",");
}
}
saveFile.write("\n");
}
saveFile.close();
}
Here is the action button for save:
saveAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
try {
// call method to save puzzle by writing its contents to an external save file
savePuzzle();
} catch (IOException ex) {
System.out.println(ex.toString());
}
}
});
Here is the code for open:
private void openPuzzle() throws FileNotFoundException, IllegalArgumentException {
JFileChooser fileChooser = new JFileChooser();
int returnVal = fileChooser.showDialog(this, "Open");
File file = fileChooser.getSelectedFile();
Scanner readFile = new Scanner(file);
// If the user has canceled, no need to continue with open process
if (returnVal != JFileChooser.APPROVE_OPTION) {
return;
}
// Row
int r = 0;
// Update squares with data from file
while (readFile.hasNextLine()) {
String[] splitLine = readFile.nextLine().split(",");
// Verify the length of the row
if (splitLine.length != 9) {
throw new IllegalArgumentException(String.format("Row length(%d) not correct in %s at row %d",
splitLine.length, file, r));
}
for (int c = 0; c < 9; c++) {
// Verify each item in row
if (splitLine[c].length() != 1 || !(Character.isDigit(splitLine[c].charAt(0)))) {
throw new IllegalArgumentException(String.format("Invalid token %s in %s at row %d col %d",
splitLine[c], file, r, c));
}
// Update square
inputBoxes[r][c].setText(splitLine[c]);
}
// Move to next row
r++;
}
}
And the open action button:
openAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
try {
// call method so that user can open their saved puzzle and populate the grid with its contents
openPuzzle();
} catch (FileNotFoundException ex) {
System.out.println(ex.toString());
} catch (IllegalArgumentException ex) {
System.out.println(ex.toString());
}
}
});
I know that the open code is finding empty values in the saved text file if it is a partially completed puzzle, and it is returning those catch statements, but I have no clue how to get it to just keep reading each element on the line (whether it's a number or empty space), and just return what's in the text file to the GUI grid (populate the grid with the corresponding numbers).
The errors I'm getting are either the "Row length %d..." error or the "Invalid token %s..." error. It loads nothing back into the grid when I select the file from the Open function. That's where I'm lost. If the puzzle is complete, and it is saved, then it can be open, because the external text file that contains the puzzle is full, and each element (space) in the file has a number in it, so when it iterates over each number, it does not find any errors or missing numbers. But when a partial file is saved, it cannot be opened back into the grid to start playing it again...
Your representation of a (sample) row is this:
1,2,,7,6,,,,5
But when you split that line on ,, you will get:
[1,2,7,6,5]
This is clearly not an array of length 9, so if (splitLine.length != 9) will return false. You must save a non-digit character to the text file that indicates an 'empty' space, or the split function will very rarely return a row of the correct length. It is possible to represent an entire Sodoku board with a single list of 81 characters, the digits 0 through 9 and an 'empty' character, no commas or line breaks needed. The key here is that the empty character is still required to maintain the topology of your data structure.
As a side note this:
if (c < ROWS - 1) {
saveFile.write(",");
}
Should probable reference COLS instead.
From reading your code it would seem to me that the offending line is:
if (splitLine[c].length() != 1 || !(Character.isDigit(splitLine[c].charAt(0)))) {
throw new IllegalArgumentException(...
In the function openPuzzle. This is because when saving a partially completed sudoku your file will look like "1,2,,3,,1,6,7,....." Now the empty cells when read in will have a string length of 0. So splitLine[c].length() != 1 will fail. To solve this i would suggest changing the code to be:
if (splitLine[c].length() > 0 || !(Character.isDigit(...
So that zero length characters (unfilled spaces) are accepted when loading it in.
I'm going to try to keep it as simple as possible. I have a Program that adds values to the table. When a button is clicked it reads values from the table, creates an object and writes to a binary file(.ser).
When I loop trough the list (e.g. 3 times if i added three object values to the table) of the table, then I create an object and write it to a file. But when I read the same file it just reads the same object ( 3 times if I added 3 objects to the Table). Why is it doing that? I'm new to Java any help would be great thanks
Object Structure
public class Empleados implements Serializable {
public int NoEmpleado;
public String ENombre;
public String EApellido;
public String EGrupo;
.
.
Setters and getters
}
Following code runs when I click a button to write to binary file (takes data from a table previously filled with data). I am also closing the file after all of this is done.
try // open file
{
outputS = new ObjectOutputStream(new FileOutputStream( "empleados.ser" ) );
} // end try
catch ( IOException ioException )
{
System.err.println( "Error opening file." );
} // end catch
for (int num = 0; num < tableModel2.getRowCount();num++)
{
try
{
empleado1.setNumero(Integer.parseInt(tableModel2.getValueAt(num, 0).toString()));
empleado1.setNombre(tableModel2.getValueAt(num, 1).toString());
empleado1.setApellido(tableModel2.getValueAt(num, 2).toString());
empleado1.setGrupo(tableModel2.getValueAt(num, 3).toString());
int n = empleado1.getNumero();
if (empleado1.getNumero() > 0)
{
outputS.writeObject(empleado1);
}
else
{
System.out.println("Numero debe ser mayor a 0.");
}
}
.
.
fallow by rest of catch stataments