Why can't I add text to a file in Java? [duplicate] - java

This question already has answers here:
How to append text to an existing file in Java?
(31 answers)
Closed 3 years ago.
It seems that its creating a new file always I try to write or read.
Each line starts with the name of the player, if exists the player should add the score at the end, if not creates a new line and write the info.
.......................
public class JogadorData {
private String nome_player;
private Scanner is;
private FileWriter os;
// this file exists
private final String path = "src/Data/JogadorData";
public JogadorData(String nome_player) {
this.nome_player = nome_player;
try {
is = new Scanner(new File(path));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
try {
os = new FileWriter(path);
} catch (IOException e) {
e.printStackTrace();
}
}
public void escreverScore(String score) {
if (jogadorNovo(nome_player)) {
try {
os.write(nome_player + " " + score);
} catch (IOException e) {
e.printStackTrace();
}
}
else {
escreverResultadoJogadorExistente(score);
}
try {
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// returns true if it is a new player
private boolean jogadorNovo(String nome_player) {
while (is.hasNextLine()) {
String linha = is.nextLine();
String[] info = linha.split(" ");
if (info[0].equals(nome_player)) {
return false;
}
}
return true;
}
}
....................................
....................................
Test:
public class TESTE {
public static void main(String[] args) {
JogadorData jogador = new JogadorData("Manelina");
jogador.escreverScore("100");
// System.out.println(jogador.lerMelhorResultado());
}
}

The example below is a simplified read/write to file from what you have, done in similar format to what you are trying to do. What this code does is reads every line from the file you are loading from via Files#readAllLines, then runs through each line, (put your logic where I commented the if statement, and then output.add appends the new version of the line you are modifying, storing it in the array list "output", after which the file is saved to the path defined by Files#write
List<String> output = new ArrayList<>();
List<String> lines = Files.readAllLines(Paths.get("Path/To/File.txt"));
for (String line : lines) {
//... if (playerExists(line))
output.add(line + " " + score);
}
Files.write(Paths.get("Path/To/Save/File.txt"), output);

Related

I want to get one line as header and rest data is append in file

I want to get one line as header and then rest of data append in the file.but i am facing issue that it is saving the header repeatedly when i have called the function.
Expected output should be like
Id : Title : Group ID
1 : ab : 2
2 : fd : 3
3 : fwsj : 3
public void writeOutputToFile(int id, String title, int groupId) throws IOException {
OutputStream os = new FileOutputStream(new File("output_report.txt"), true);
os.write("\n Id Title Group ID \n ".getBytes());
os.write((id + " " +title + " " + groupId + "\n").getBytes());
os.close();
}
well, inside your method you write the headers to the file, so obviously whenever you call it they'll get written..
You can separate it to two methods- one that writes the headers (and called only once) and another that writes the data (and called once per row).
Alternatively, use some sort of loop inside your method to write each of the lines to the file, after writing the headers once.
The Problem
It is repeatedly putting in the header, because when you call the method, you are always going to insert the header. Instead, you may want to code a util that inputs headers for a file you are creating, and then a separate method for inserting the data.
The Solution
Solution 1)
The helper util method would look something like this:
// String... allows for multiple string parameters to be entered for all of your headers.
public void prepFile(File f, String... headers) {
StringBuffer buffer = new StringBuffer();
for (String header : headers) {
buffer.append(header + "\t");
}
OutputStream os = new FileOutputStream(f, true);
os.write(buffer.toString().getBytes());
os.close();
}
After the file is prepped, you can then use your writeOutputToFile method for all the data.
Edit
Solution 2)
If you were going to make a stand alone class for this, I would recommend you set it up like so:
import java.io.*;
public class OutputFile {
private File file;
private String[] headers;
private boolean existed;
public OutputFile(File f, String... headers) {
this.file = f;
this.headers = headers;
init();
}
private void init() {
existed = file.exists();
// If the file didn't exist, then you want to create it.
if (!existed) {
try {
file.createNewFile();
// Afterwards, you can then write your headers to it.
if (headers != null) {
writeData(headers);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void writeData(int id, String title, int groupId) {
writeData("" + id, title, "" + groupId);
}
public void writeData(String... strings) {
StringBuffer buffer = new StringBuffer();
for (String s : strings) {
buffer.append(s + "\t");
}
buffer.append("\n");
writeData(buffer.toString());
}
public void writeData(String data) {
OutputStream os = null;
try {
os = new FileOutputStream(file, true);
os.write(data.getBytes());
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

How to split Set<E>?

I have class Laptops. Inside this class I have 3 parameters "String name, Integer screen, Integer price" I created Set and now I need to split it and compare with price if price over 2000$ write to file if lower write to second file.
This is my method:
public void check(Set<Laptops> laptops, File under2000, File over2000){
try{
String under2000 = "2000";
OutputStream under = new FileOutputStream(under2000);
PrintStream printStream = new PrintStream(under);
Iterator<Laptops> lap = laptops.iterator();
while (lap.hasNext()){
lap.next();
if (laptops.contains(under2000)) {
printStream.print(lap);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
Can someone help me?
It is easy to split the set with streams:
Set<Laptops> over2000 = laptops.stream().filter(l -> l.getPrice() > 2000).collect(Collectors.toSet());
Set<Laptops> rest = new HashSet<>(laptops);
rest.removeAll(over2000);
The first part filters all laptops with price over 2000. The rest takes the original set and removes those laptops. Than you can handle each set as you like.
public void check(Set<Laptops> laptops, File under2000file, File over2000file){
try {
PrintStream under2000 = new PrintStream(under2000file);
PrintStream over2000 = new PrintStream(over2000file);
for(Laptop laptop: laptops) {
if(laptop.getPrice() < 2000) {
under2000.println(laptop);
} else {
over2000.println(laptop);
}
}
under2000.close();
over2000.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}

How to overwrite a file that is altering an arraylist

I'm writing a program in order to keep track of DVDs in my library. I'm having trouble altering the text file that saves an added or removed DVD object from the arraylist. Whenever I call my save method, which is the one that overwrites the existing text file holding all the information, it will not change it whatsoever. My add and remove methods work fine but it's just the save method which overwrites the file that I'm reading from that will not work. The following code is what I was attempting to use to save the arraylist to the file. My filename is DVDCollection.txt and the boolean variable flag is a static variable used to check whether or not the code which adds or removes an object from the arraylist was reached.
public void save() {
try{
if(flag=true){
FileWriter instream = new FileWriter("DVDCollection.txt",false);
instream.close();
}else{
return;
}
}catch(IOException e){
System.out.println("The file could not be written to!");
}
}
If you are using java 8 or above it's as simple as:
List<String> lines = Arrays.asList("first line", "second line");
try {
Files.write(Paths.get("my-file.txt"), lines);
} catch (IOException e) {
//handle exception
}
Make sure you provide the right path!
Not sure, why this method should save an array list, as the actual code that writes to this file is missing. Here is simple test, let's start here:
import java.io.*;
import java.util.*;
public class FileSaveTest {
public static void main(String[] args) {
FileSaveTest test = new FileSaveTest();
test.fill();
test.save();
}
public void fill() {
arrayList.add("My disc 1");
arrayList.add("My disc 2");
arrayList.add("Another disc");
}
public void save() {
try {
if(flag) { // you dont need ==true
FileWriter instream = new FileWriter("DVDCollection.txt",false);
for (String entry : arrayList) {
instream.write(entry + "\n");
}
instream.close();
} else {
return;
}
} catch(IOException e) {
System.out.println("The file could not be written to!");
}
}
private ArrayList<String> arrayList = new ArrayList<>();
private static boolean flag = true;
}
Next, it's not very good, to close the file in such manner. If an exception occurs while writing, the file will not be closed. instream.close() should be put into the "finally" block. This block will be executed in any case, regardless of whether an exception occurred or the return keyword met:
public void save() {
Writer instream = null;
try {
if(flag) { // you dont need ==true
instream = new FileWriter("DVDCollection.txt",false);
for (String entry : arrayList) {
instream.write(entry + "\n");
}
} else {
return;
}
} catch(IOException e) {
System.out.println("The file could not be written to!");
} finally {
try {
if (instream != null)
instream.close();
} catch (IOException e) {
System.err.println("Exception during close");
}
}
}
Or, if you are using java 7, you can use try-with-resources syntax:
public void save() {
if(flag) { // you dont need ==true
try (Writer instream = new FileWriter("DVDCollection.txt",false)) {
for (String entry : arrayList)
instream.write(entry + "\n");
} catch(IOException e) {
System.out.println("The file could not be written to!");
}
} // you dont need "return else { return; }" anymore
}

How to sort a text file and save it using java?

I have been asked to make a quiz and in the end of the quiz, what I want to keep are in two separate arrays names[] and scores[]. I have been asked to save the scores in a file using input and output. I have managed to do everything and successfully output the results and save it into the files (e.g. highscores.txt)
the results are saved like this:
4
name10
name5
name4
name2
the first line indicates how many scores there are in the file as every person who plays the quiz has their score saved.
What I am struggling to do is sort the scores to be placed in order of highest to lowest.
I have tried sorting the scores before they are saved in the file but the older scores in the file will not be sorted anymore. Example:
8
newname10
newname9
newname8
newname7
name10
name5
name4
name2
im only a beginner so go easy...
Well, because you don't use any kind of formatting to easily distinguish between username and score (eg: [username]:[score]) you've the problem to separate these two information from each other afterwards.
Anyhow - you need to load the data and reorder them trying to separate the username from the score. Read the file line my line and split the name from the score using regexp (in hope that the user name contains only letters): Pattern.compile("(\w+)(\d+)"). You can then use Matcher to get group 1 (the Name) and group 2 (the score). Then you can compare the score and reorder the List
What you should do is to create class Person which implements Comparable<Person> and if you are little bit lazy and the amount of data is not large Serializable too.
Then put everything inside TreeSet<Person> and write methods which serialize the TreeSet and deserialize it too.
Like this:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.TreeSet;
public class Person implements Comparable<Person>, Serializable {
private String name;
private int score;
public Person(String name, int score) {
this.name = name;
this.score = score;
addPerson(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
#Override
public int compareTo(Person o) {
return score - o.score;
}
#Override
public String toString() {
return "Person [name=" + name + ", score=" + score + "]";
}
private static TreeSet<Person> classExtension = new TreeSet<Person>();
private static void addPerson(Person person) {
classExtension.add(person);
}
private static void removePerson(Person person) {
classExtension.remove(person);
}
private static void showExtension() {
for (Person person : classExtension)
System.out.println(person);
}
public static void serialize() {
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream("Person.ser");
oos = new ObjectOutputStream(fos);
oos.writeObject(classExtension);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (oos != null)
oos.close();
} catch (IOException e) {
}
try {
if (fos != null)
fos.close();
} catch (IOException e) {
}
}
}
public static void deserialize(){
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream("Person.ser");
ois = new ObjectInputStream(fis);
classExtension = (TreeSet<Person>) ois.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
// zasoby zwalniamy w finally
try {
if (ois != null) ois.close();
} catch (IOException e) {}
try {
if (fis != null) fis.close();
} catch (IOException e) {}
}
}
}
If you're already able to sort the results before writing them to the file, why don't you read all the file before updating It? Then you can put the old data stored in your data structure with the new data,and sort them alla together. Then you should overwrite the old file with the data you already have.
This way could be expensive if your file has a lot of record.
The best way could be to use a collection that keep items in order. Take a look to PriorityQueue class. Then just store it into the file,and load It before adding new elements.
You can write the PriorityQueue to a file using an ObjectOutputStream and read it back with an ObjectInputStream.
This little program should do the Job.
Bear in mind that this really just sorts a text-file. If you need further processing according to your problem, modify it.
public class LineReader {
public static void main(String[] args) {
String file = args[0];
List<String> _list = new ArrayList<String>();
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
for (String line; (line = br.readLine()) != null;) {
_list.add(line);
}
} catch (Exception ex) {
}
java.util.Collections.sort(_list, String.CASE_INSENSITIVE_ORDER);
try(FileWriter writer = new FileWriter(file)) {
for (String str : _list) {
writer.write(str + "\n");
}
writer.close();
} catch (IOException ex) {
}
}
}

A properties file I created in the 1st run gets blanked in the 2nd run

Okay, I'm trying to create a custom client for Minecraft (don't worry, my question has nothing to do with Minecraft in particular), and I added an abstract class to manage a configuration file using Java's built-in Properties system. I have a method that loads a properties file or creates it if it doesn't already exist. This method is called at the beginning of all my other methods (although it only does anything the first time its called).
The properties file gets created just fine when I run Minecraft the first time, but somehow when I run it the second time, the file gets blanked out. I'm not sure where or why or how I'm wiping the file clean, can someone please help me? Here's my code; the offending method is loadConfig():
package net.minecraft.src;
import java.util.*;
import java.util.regex.*;
import java.io.*;
/**
* Class for managing my custom client's properties
*
* #author oxguy3
*/
public abstract class OxProps
{
public static boolean configloaded = false;
private static Properties props = new Properties();
private static String[] usernames;
public static void loadConfig() {
System.out.println("loadConfig() called");
if (!configloaded) {
System.out.println("loading config for the first time");
File cfile = new File("oxconfig.properties");
boolean configisnew;
if (!cfile.exists()) {
System.out.println("cfile failed exists(), creating blank file");
try {
configisnew = cfile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
configisnew=true;
}
} else {
System.out.println("cfile passed exists(), proceding");
configisnew=false;
}
FileInputStream cin = null;
FileOutputStream cout = null;
try {
cin = new FileInputStream(cfile);
cout = new FileOutputStream(cfile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (!configisnew) { //if the config already existed
System.out.println("config already existed");
try {
props.load(cin);
} catch (IOException e) {
e.printStackTrace();
}
} else { //if it doesn't exist, and therefore needs to be created
System.out.println("creating new config");
props.setProperty("names", "oxguy3, Player");
props.setProperty("cloak_url", "http://s3.amazonaws.com/MinecraftCloaks/akronman1.png");
try {
props.store(cout, "OXGUY3'S CUSTOM CLIENT\n\ncloak_url is the URL to get custom cloaks from\nnames are the usernames to give cloaks to\n");
cout.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
String names = props.getProperty("names");
System.out.println("names: "+names);
try {
usernames = Pattern.compile(", ").split(names);
} catch (NullPointerException npe) {
npe.printStackTrace();
}
System.out.println("usernames: "+Arrays.toString(usernames));
configloaded=true;
}
}
public static boolean checkUsername(String username) {
loadConfig();
System.out.println("Checking username...");
for (int i=0; i<usernames.length; i++) {
System.out.println("comparing "+username+" with config value "+usernames[i]);
if (username.startsWith(usernames[i])){
System.out.println("we got a match!");
return true;
}
}
System.out.println("no match found");
return false;
}
public static String getCloakUrl() {
loadConfig();
return props.getProperty("cloak_url", "http://s3.amazonaws.com/MinecraftCloaks/akronman1.png");
}
}
If it's too hard to read here, it's also on Pastebin: http://pastebin.com/9UscXWap
Thanks!
You are unconditionally creating new FileOutputStream(cfile). This will overwrite the existing file with an empty one. You should only invoke the FileOutputStream constructor when writing a new config file.
if (configloaded)
return;
File cfile = new File("oxconfig.properties");
try {
if (cfile.createNewFile()) {
try {
FileOutputStream cout = new FileOutputStream(cfile);
props.setProperty("names", "oxguy3, Player");
props.setProperty("cloak_url", "http://...");
...
cout.flush();
} finally {
cout.close();
}
} else {
FileInputStream cin = new FileInputStream(cfile);
try {
props.load(cin);
} finally {
cin.close();
}
}
configloaded=true;
} catch(IOException ex) {
e.printStackTrace();
}

Categories