I have a simple text file with information in it called logindata.txt . And it looks like this:
username1:password1:username2:password2
The plan is to split the line at the " : " symbol.
This is my code so far...
(...)
final StringBuilder text = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(file));
try {
String line;
while ((line = br.readLine()) != null) {
text.append(text);
//stuff over here ?
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
This works perfectly fine if my file only has one word in it.
But I want to use the file to store all the usernames and passwords (This is only for learning purposes I know it's a bit stupid) in the end like this:
(...)
login_button.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
if (username.getText().toString().equals(text.toString()) && password.getText().toString().equals(text.toString()))
//Stuff happening here if the username & password is correct...
(...)
I'm completely stuck and have tried many examples for splitting a string and none seem to work.
In your case I would like to use a Map<Username, Password> with Pattern like this :
String line = "username1:password1:username2:password2";
Map<String, String> userPass = new HashMap<>();
Pattern pattern = Pattern.compile("([^:]+):([^:]+)");
Matcher matcher = pattern.matcher(line);
while (matcher.find()) {
userPass.put(matcher.group(1), matcher.group(2));
}
System.out.println(userPass);
Outputs
{username2=password2, username1=password1}
If you want to check if the user exist or not, you can use :
String username = "username1";
String password = "password1";
if(userPass.containsKey(username) && userPass.get(username).equals(password)){
//User exist
}
In case you values can be repeated you can use another structure or create a new Object which hold username and password, instead of a map
a general code would be for splitting text would be
class Main {
public static void main(String[] args) {
String text = "username1:password1:username2:password2";
String[] vals = text.split(":");
for (String temp: vals){
System.out.println(temp);
}
}
}
To split a String in java, you could use String#split(string regex).
In your case, after have the file read into a String, you could put all pairs of username/password into a HashMap for lookup.
String text = "username1:password1:username2:password2"; // you would read it from the file
String[] segments = text.split(":"); // split the string with ":"
Map<String, String> userPassMap = new HashMap<>(); // initialize the map to store user info
for (int i = 0; i < segments.length; i+=2) {
userPassMap.put(segments[i], segments[i+1]);
}
And for your login validation
login_button.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
String user = username.getText().toString().trim(); // trim() to get rid of heading and trailing empty spaces
String pass = password.getText().toString().trim();
if (userPassMap.containsKey(user) && userPassMap.get(user).equals(pass)) {
//Stuff happening here if the username & password is correct...
}
(...)
Related
So i got a Java Class of Konto, which got:
private String navn;
private int medlemdsnummer;
private String årstal;
private String måned;
private String dag;
LocalDate localDate;
They are used like this:
ArrayList<Konto> kontoArrayList = new ArrayList<>();
And I save my ArrayList to a .txt document before the program shutdowns:
private static void saveToFile(ArrayList<Konto> kontoArrayList) throws IOException {
String content = new String(Files.readAllBytes(Paths.get("medlemmer.txt")));
PrintStream printStream = new PrintStream("medlemmer.txt");
for (int i = 0; i < kontoArrayList.size(); i++) {
printStream.println(content + kontoArrayList.get(i).getMedlemdsnummer() + ": " + kontoArrayList.get(i).getNavn() + " " +
kontoArrayList.get(i).getLocalDate());
}
}
They end up looking like this in the .txt file:
1: Kasper 1996-11-20
2: Jonas 1996-04-27
3: Jesper 1996-05-14
Okay, so far so good. Now for the question: When the program is turned on, I want to make it able to load the .txt file from the beginning and "transfer" it to an ArrayList of Konto. So that i later can use my method (addNewMember). I saw a lot of example on the internet, but they all use:
ArrayList<String> somename = new ArrayList<String>();
I want to use:
ArrayList<Konto> konto = new ArrayList<Konto>();
Is this possible, if so how do to?
If not what could i do instead?
Thanks in advance, Victor.
You can read all lines from the file as string and split this strings by spaces.
And then create new objects with parsing of options.
Something like this:
List<String> strings = Files.readAllLines(Paths.get("test.txt"));
List<Konto> kontos = new ArrayList<>();
for (String string : strings) {
String[] data = string.split(" ");
kontos.add(new Konto(data[1], new Date(data[2])));
}
Or using Streams:
List<Konto> kontos = Files.lines(Paths.get("test.txt")) // String
.map(line -> line.split(" ")) // String[]
.map(data -> new Konto(data[1], new Date(data[2])) // Konto
.collect(Collectors.toList());
Something like the following, you've got to check it
class TestParse {
public TestParse(String line) {
StringTokenizer tokenizer = new StringTokenizer(line, ",");
if(tokenizer.countTokens() != 3) {
throw new RuntimeException("error");
}
s1 = tokenizer.nextToken();
s2 = tokenizer.nextToken();
s3 = tokenizer.nextToken();
}
private String s1;
private String s2;
private String s3;
}
public class TestRead {
public static void main(String[] args) throws Exception {
List<TestParse> testParses = new ArrayList<TestParse>();
BufferedReader in = new BufferedReader(new FileReader("file.txt"));
String line;
while((line = in.readLine()) != null) {
testParses.add(new TestParse(line));
}
in.close();
}
}
I think one way you can try is read line by line, and define a Konto constructor that accept a string.
Edit: You can follow the below answer from Lucem. But I think I will do it a little different
List<String> strings = Files.readAllLines(Paths.get("fileName.txt"));
List<Konto> kontos = new ArrayList<>();
for (String s: strings) {
kontos.add (new Konto(s))
}
or using Streams:
List<Konto> kontos = Files.lines(Paths.get("fileName.txt"))
.map(line -> new Konto(line));
.collect(Collectors.toList());
And then in Konto class add a constructor that accept a string and manipulate it. Because you didn't add the class Konto here, I didn't know the exact name of your properties, so I let it be "yourPropertyNumber", "yourPropertyString" and "yourPropertyDate"
class Konto {
public Konto (String input) {
// Split based on white space
String[] dataParts = input.split(" ");
// Get rid of the semicolon
String number = dataParts[0].substring(0, dataParts[0].length - 1);
yourPropertyNumber = parseInt(number);
yourPropertyString = dataParts[1];
yourPropertyDate = new Date(dataParts[2]);
}
// Your other code here
}
The reason I want to pass a String to a constructor rather than parse the string where I read the file is that I think it is easier to debug or make change in the way it reads the string.
Hope this help.
I have a .txt file reader, which reads individuals lines of a file and stores them in a List<String> which I then display on a JTextArea. Some of the lines contain \n, because I wanted specific breaking when displaying. However, when I do display the code, the \nare shown instead of breaking the line as they usually do.
I tried replacing the \n's with linebreaks by placing the code str.replaceAll( "\\\\n", System.lineSeperator()); in the while loop, before list.add(str); but it doesn't seem to have any effect.
To reiterate, I simply need a way to change the \n's to linebreaks. Any help would be much appreciated.
The code for the .txt reader is below.
static void parseStringArray(final String filePath, List<String> list){
try {
InputStream input = Text.class.getResourceAsStream(filePath);
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String str;
while((str = reader.readLine()) != null){
list.add(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
**Edit - I have updated the post to include a bit more code.
The List I send in as an argument is initialized before the method. It is
protected static List<String> textfiles = new ArrayList<String>();
An example of a line from the .txt file is
Welcome!\n\n If you wish to proceed, please type the password below.\nEnjoy your stay!
The code to display this text is below. (Pardon formatting)
Timer teletypeTimer = null;
public static void animateTeletype(final JTextArea displayArea)
{
final String[] s = new String[1];
s[0] = "";
final int[] i = new int[2];
i[0] = 0;
i[1] = 0;
teletypeTimer = new Timer(20, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(i[0]==0)
displayArea.setText("");
s[0] = TTqueue[i[1]].substring(i[0], i[0]+1);
i[0]++;
displayArea.append(s[0]);
if(displayArea.getText().equals(TTqueue[i[1]]))
{
i[1]++;
if(TTqueue[i[1]] !=null)
{
teletypeTimer.stop();
i[0] = 0;
timerRestart(5000, teletypeTimer);
}
else
{
Arrays.fill(TTqueue, null);
complete=true;
teletypeTimer.stop();
}
}
}
});
teletypeTimer.start();
}
(Posted on behalf of the OP).
I switched replaceAll() with replace() and worked with Pshemo and Nick Vanderhoven's points. I added the line of code str = str.replace("\\n", System.lineSeparator()); as suggested by Pshemo, and that's done the trick. Cheers!
I have class Account which have username, fullName, password, id and points.
All accounts are saved in a file.I have many accounts in my file, not just one. This is example of one account in text file.
Miljan9602 Rakita Miljan miljan123 1463433398614 0.0
username, full name, password, id and points
Now, for example if i want to change points for my username. First thing i would do is go through all lines in file and compare all usernames, if i find equal username. I would change point's. This is my idea how to do it. Just dont know how to edit it in file.
public void edit(String username, double points)
{
File f = new File("Accounts.txt");
// file doesnt exist, return from method
if(!f.exists())
return;
Scanner sc = null;
try
{
sc = new Scanner(f);
while(sc.hasNextLine())
{
String line = sc.nextLine(); // Take whole line
String split[] = line.split(" "); // Split it so i can check username
if(split[0].equals(username))
{
String change = Double.toString(points); // Make string from double
split[5] = change; // on fifth index are points
/* My question is now how to edit file and to replace my new points
* with old points ?
* Miljan9602 Rakita Miljan miljan123 1463433398614 0.0 <- Need to change this 0.0 with split[4];
*/
}
}
}catch(Exception e)
{
e.printStackTrace();
}finally{
// finally will always close file
sc.close();
}
You could use the Apache's Commons IO library. Everything you'll need, and more, can be found there. Also, here is the GitHub mirror of Commons IO. Worth a look through.
{
File f = new File("Accounts.txt");
FileWriter fw = new FileWriter(f);
// file doesnt exist, return from method
if(!f.exists())
return;
Scanner sc = null;
try
{
sc = new Scanner(f);
while(sc.hasNextLine())
{
String line = sc.nextLine(); // Take whole line
String split[] = line.split(" "); // Split it so i can check username
if(split[0].equals(username))
{
String change = Double.toString(points); // Make string from double
split[5] = change; // on fifth index are points
/* My question is now how to edit file and to replace my new points
* with old points ?
* Miljan9602 Rakita Miljan miljan123 1463433398614 0.0 <- Need to change this 0.0 with split[4];
*/
for(int i = 0; i < spit.length(); i++{
fw.write(split[i] + " ");
}
System.getProperty("line.separator");
}
}
}catch(Exception e)
{
e.printStackTrace();
}finally{
// finally will always close file
sc.close();
fw.close();
}
This should work
As one has to write the entire read text back to the file system, use Files.readAllLines().
Path path = Paths.get(".../Accounts.txt");
Charset charset = StandardCharsets.UTF_8;
List<String> lines = new ArrayList<>();
if (Files.exists()) {
Files.readAllLines(path, charset);
for (int i = 0; i < lines.size(); ++i) {
String split[] = lines.get(i).split(" ");
if (split[0].equals(username)) {
String change = String.valueOf(points);
split[5] = change; // on fifth index are points
StringBuilder sb = new StringBuilder();
for (String value : split) {
if (sb.length() != 0) {
sb.append(' ');
}
sb.append(value);
}
lines.set(i, sb.toString()); // Changes the line.
Files.write(path, lines, charset);
break; // leave loop
}
}
}
More explained
To alter a single line of a text file, one in principle has to load the entire text and after altering the line, safe it entirely.
The reason is that the file can shrink or grow, depending on the line changes.
Even with some twists this is not optimal.
Files.readAllLines is a nice method for that. One might also change the format:
Fixed length records (lines) allow a RandomAccessFile. However a text risks being manually edited so the file gets corrupted, and one also has limited field lengths.
The .properties format allows access with the Properties class. Requirement is a key, and a format key = value. Also the text has some escaping (\).
One could keep Accounts.txt in core, say in a class Accounts, representing all as a Map from user name to Account.
class Account {
public final String userName; // Unmodifiable key
public String password;
...
}
class Accounts {
private Map<String, Account> accountsByUserName = new HashMap<>();
public void loadAccounts() throws IOException { ... }
public void saveAccounts() throws IOException { ... }
public Optional<Account> getAccountByUserName(String userName) { ... }
public void deleteAccountByUserName(String userName) { ... }
public void createAccount(Account account) throws AlreadyExistsException { ... }
}
I have a csv file like this:
"user1","track1","player1"
-------------------------
"user1","track2","player2"
-------------------------
"user1","track3","player3"
-------------------------
"user1","track4","player4"
-------------------------
"user2","track2","player3"
-------------------------
.
.
"userN","trackM","playerX"
What I need to do is to divid tracks and players related to each user into a half and put them in separate files.
For example, for user1, if it has 4 lines, I need to divid it into two parts (the first two lines in file A, and the rest in file B), and repeating the same action for all users.
This is what I wrote so far:
public static void main(String[] args) throws java.lang.Exception {
BufferedReader userlines = new BufferedReader(new FileReader("/Users/mona/Documents/Bolzano/Datasets/Lastfm_Matthias/lastfm_usertrackplayer.csv"));
String uLine = null;
while ((uLine = userlines.readLine()) != null) {
String[] userId = uLine.split(",");
ArrayList<String> list = new ArrayList<String>();
list.add(uLine);
for(int i=0; i<=list.size();i++){
// --> THIS FOR CONDITION IS MY PROBLEM,I need s.th like for(i=0; i<=(last unique userId (i.e., length of userId[i]) until it reaches the next unique userId)
//Divide the lines and put into two separate files
}
}
userlines.close();
}
Sorry I know it should be something simple, but I really could not find any related/similar question by googling my problem :(
Could someone help me please?
Thanks
You cannot know "a priori" the number of lines for each user.
So you must memorize (in a List for example) all lines for the current user until you read the next user. Then save, in both files, the content of the list.
Clean the list, do the same thing for the next user.
EDIT
public static void main(String[] args) throws java.lang.Exception {
try(BufferedReader userlines = new BufferedReader(new FileReader("/Users/mona/Documents/Bolzano/Datasets/Lastfm_Matthias/lastfm_usertrackplayer.csv"));) {
String uLine = null;
ArrayList<String> list = new ArrayList<String>();
String currentUserId = null;
while ((uLine = userlines.readLine()) != null) {
String[] userData = uLine.split(",");
String userId = userData[0]; // <-- get User ID here
if (userId.equals(currentUserId)) {
// Do what ever you need while buffering same userId
} else {
// Save currentUserId in file
yourSaveMethod(list);
currentUserId = userId;
list.clear();
}
list.add(uLine);
}
}
}
You can use StringTokenizer class for parsing data.
Example:
String str = "user1, track1, player1";
StringTokenizer st = new StringTokenizer(str);
System.out.println("---- Split by space ------");
while (st.hasMoreElements()) {
System.out.println(st.nextElement());
}
System.out.println("---- Split by comma ',' ------");
StringTokenizer st2 = new StringTokenizer(str, ",");
while (st2.hasMoreElements()) {
System.out.println(st2.nextElement());
}
i'm a beginner at java and still learning so please excuse my question if it sounds stupid.
i've been stuck on a straight forward problem i was given:
i'm supposed to read a text file and store the values of the text file in different variables. my text file looks like:
foo.txt
Directory_path=C:\University
school_name=SyracuseUni
i want to store the directory path and school_name in a new variable say
var_one = C:\University
and var_two = SyracuseUni
I was able to split it but in a single string.
public static void main(String[] args) throws IOException {
try {
BufferedReader br = new BufferedReader(new FileReader("C:\\foo.txt"));
String strLine = null;
String var_one = null;
String var_two = null;
while ((strLine = br.readLine()) != null) {
String[] parts = strLine.split("=");
String parameter = parts[1];
System.out.println(parameter);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
this gives me an output like this which isn't how i want it:
C:\University
SyracuseUni
i will appreciate if anyone can guide me towards the right approach. thanks all.
There is already a simple way to deal with such files using java.util.Properties class. This could be an overkill if you are simply trying to learn how to read a file.
public static void main(String[] args) {
String myVar1 = null;
String myVar2 = null;
Properties prop = new Properties();
InputStream input = null;
try (FileInputStream input = new FileInputStream("pathToYourFile")) {
prop.load(input);
myVar1 = prop.getProperty("Directory_path");
myVar2 = prop.getProperty("school_name");
} catch (IOException ex) {
//Handle exception
}
}
Something simple would be using Java Properties. You could also store values in a map. If you really insisted on filling two separate varibles, you could always count how many lines you've went across in your while loop and use switch/case to determine which variable to fill.
public static void main(String[] args) throws IOException {
try {
BufferedReader br = new BufferedReader(new FileReader("C:\\foo.txt"));
String strLine = null;
HashMap<String, String> map = new HashMap<String, String>();
while ((strLine = br.readLine()) != null) {
String[] parts = strLine.split("=");
map.put(parts[0], parts[1]);
}
for (Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + " = " + value);
}
}
catch (IOException e) {
e.printStackTrace();
}
}