I want to read input from a text file in the following order
Read in a url into a String variable, Read in all words after that url into an ArrayList variable. The next time I encounter a url, I want to call a method to perform operations on what I read in so far, before setting the new url into the original String variable and so on.
What I have done so far is
public void read() throws IOException {
PerformCheck pc = new PerformCheck();
Scanner sc = new Scanner(new File("input.txt"));
sc.useDelimiter(",");
String url ="";
String res ="";
ArrayList tmp = new ArrayList();
while (sc.hasNext()) {
String s = sc.next().trim();
if (s.contains("http")){
url = s;
}
else {
tmp.add(s);
if (sc.next().contains("http")){ //getting error here
result= pc.perform(url,tmp);
url= "";
tmp= null;
}
}
}
sc.close();
}
The comment in the code - is where I think I am getting error. Basically, I am trying to look ahead to see if the next token is a url, how can I do this right?
my input file looks like this
url, word1,word2,word3 url2, word1,word2,word3
You could save the first time the url and at the second url you check without a lock:
Looks like that:
public void read() throws IOException {
PerformCheck pc = new PerformCheck();
Scanner sc = new Scanner(new File("input.txt"));
sc.useDelimiter(",");
String url = "";
String res = "";
boolean lock = true;
ArrayList<String> tmp = new ArrayList<String>();
while (sc.hasNext()) {
String s = sc.next().trim();
boolean isHttp=s.contains("http");
if (isHttp && lock) {
url = s;
lock=false;
}
else if (isHttp){
result= pc.perform(url,tmp);
url= s;
tmp= new ArrayList<String>();
// Perform check here
// url=s
//tmp=new ArrayList<String>();
}else {
tmp.add(s);
}
}
if (tmp.size()>0){
result=pc.perform(url,tmp);
}
sc.close();
}
The lock is only for the first time where you find a url.
The problem is that there is no "looking ahead" in a scanner. Once you use next() it actually attempts to read the next item. And if it hit the end of the file by then, then there won't be a next item, and you'll get an error.
That's why one must always check hasNext(), and always perform just one next() per hasNext() (no matter if it's next(), nextInt(), nextDouble() or whatever).
The usual way to deal with such requirements is keep whatever you have read so far, and look at the current item that you have read. If it's a URL, you know you should use whatever you collected so far. In pseudo-code:
put null in url
put null in list
open the scanner
while there is a next item in the scanner
set temp to the next item
if temp is a URL
if url has a value
process url and list
end if
put temp in url
create an empty list
else
add temp to list
end if
end while
process the url and list
The part that says "if url has a value" means that this is not the first URL that we are reading. That is, url != null.
So when you encounter a URL, there are things you do only if there is a previous URL (process the previous data), and there are things you always do (assign the new URL, prepare a new list. If you don't prepare a new list you'll also get an error!).
And if you don't encounter a URL, you know that you already have a prepared list, and you add the item to it.
This way, there is no looking ahead - only looking back.
But it means that after the loop you have a URL and a list that were not processed yet, so that's why you need to perform the "process" operation again.
public void read() throws IOException {
PerformCheck pc = new PerformCheck();
Scanner sc = new Scanner(new File("input.txt"));
sc.useDelimiter(",");
String url ="";
String res ="";
boolean firstURLFound = false;
List<String> tmp = new ArrayList<String>();
while (sc.hasNext()) {
String s = sc.next().trim();
if (firstURLFound && s.contains("http")){
result= pc.perform(url,tmp);
url= "";
tmp= new ArrayList<String>();
firstURLFound = false;
}
if (s.contains("http")){
firstURLFound =true;
url = s;
}
else {
tmp.add(s);
}
}
sc.close();
}
Related
I have a situation similar where I need to change a line in a batch file if similar string not found.
Suppose I have a code like below in batch(I know it is not correct code as it a dummy only)
public static void main(String[] args) {
if (user == '1234') {
ENV DEV
set DB myDBDEV
set Excel myExecelDEV
set API MyAPIURLDEV
} elseif (user == '5678') {
ENV UAT
set DB myDBUAT
set Excel myExecelUAT
set API MyAPIURLUAT
}
}
}
Now I want java to read above file, find ENV as DEV and change the value like myDBDEV, myExecelDEV, MyAPIURLDEV etc.
I am able to find the line number by using below code
FileInputStream fis = new FileInputStream("C:\\Users\\owner\\Desktop\\batch\\MYbatch-env.csh");
InputStreamReader input = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(input);
String data;
String result = new String();
int i=0;
while ((data = br.readLine()) != null) {
i++;
if(data.contains("ENV DEV")) {
System.out.println("line number -> "+i);
}
result = result.concat(data + "\n");
}
I have tried below code but that was not return line number so I use above approach
Finding line number of a word in a text file using java
I also tried below approach but it seems not working
How to replace an string after a specific line in a file using java
Now problem statement is replaceAll function will remove all key but I want to remove the next string of key means value. and it is a text as string not a hashmap kind thing,
In if block if DB string is myDBDEV2 then I want to change the values to myDBDEV
Example:
If below string found
ENV DEV
Then below value should check value of key DB and replace if not found required value
set DB myDBDEV
set Excel myExecelDEV
set API MyAPIURLDEV
And main thing is code should make change in if block only, else if variables should be affected as an file example I have shown in above URL.
Below solution work for me
public static void main(String[] args) throws Exception {
String filepath= "C:\\Users\\Demo\\Desktop\\batch\\Demo.sh";
FileInputStream fis = new FileInputStream(filepath);
InputStreamReader input = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(input);
String data;
String result = new String();
int lineNumber=0;
int i=0;
while ((data = br.readLine()) != null) {
i++;
if(data.contains("My String data")) {
System.out.println("line number -> "+i);
lineNumber=i;
break;
}
result = result.concat(data + "\n");
}
br.close();
lineNumber=lineNumber+1;
System.out.println(lineNumber);
String Mystring =" Mystring";
String Mystringline = Files.readAllLines(Paths.get(filepath)).get(lineNumber-1); // get method count from 0 so -1
System.out.println("Line data ->> "+Mystringline);
if(!Mystringline.equalsIgnoreCase(Mystring)) {
setVariable(lineNumber, Mystring, filepath);
}else {
System.out.println("Mystring is already pointing to correct DB");
}
System.out.println("Succesfully Change");
}
public static void setVariable(int lineNumber, String data, String filepath) throws IOException {
Path path = Paths.get(filepath);
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
lines.set(lineNumber - 1, data);
Files.write(path, lines, StandardCharsets.UTF_8);
}
}
I am trying to break down a data text file which is in the format of:
kick, me, 10
kick, you, 20
into arrayList<customlist> = new arrayList
class customlist
{
string something, string something2, int times
}
So my question is how can I get each part of the text file data to each part of the customlist.
eg: kick -> something, me -> something2 and 10 -> times
Try to split each line into its components using String.split(",").
Apply String.trim() to each member in order to get rid of the spaces.
There are many way to solve this type of problem, here you can simply read all text from that text file by using InputStream and BufferReader after geting all text you can do somthing like:-
ArrayList<CustomList> getArrayList(String textFileData)
{
ArrayList<CustomList> customLists = new ArrayList<>() ;
String data[] = textFileData.split(",");
int i = data.length;
int position = 0;
while (position<i)
{
String somthing = data[position];
String somthing1 = data[position+1];
String temp = data[position+2].split(" ")[0];
int times = Integer.parseInt(temp);
CustomList customList= new CustomList();
customList.setSomething(somthing);
customList.setSomething2(somthing1);
customList.setTimes(times);
customLists.add(customList);
position = position+3;
}
return customLists;
}
Note: this is refer if you are using same string pattern as you mention in the above problem
Using a Scanner object to read the lines and breaking up each line using the split() function. Then, create a new customlist object, and add it into your ArrayList<customlist>.
public void readFile(File file, ArrayList<customlist> myList)
{
Scanner sc = new Scanner(file);
String line;
while(sc.hasNextLine())
{
line=sc.nextLine();
String[] fields = line.split(",");
int times = Integer.parseInt(fields[2].trim());
customlist myCustom = new myList(fields[0].trim(), fields[1].trim(),
times);
myList.add(myCustom);
}
sc.close();
}
You may also handle exceptions if you think its necessary.
I'm looping through text file and need to compare the contents of the text file to parameters being submitted by a user. The code I've written so far will only compare the last value in the text file.
Question: How would I continually loop and check the contents V parameters passed, stopping when there's a match between the two?
Here's what I have so far:
public boolean isAuthenticated(String username, String password) throws FileNotFoundException{
boolean status = true;
File file = new File("C:\\" "\\" "\\login.txt");
Scanner scan = new Scanner(file);
List<Login> login = new ArrayList<Login>();
while(scan.hasNextLine()){
String line = scan.nextLine();
String [] details = line.split(":");
String storedUsername = details[0];
String storedPassword = details[1];
Login l = new Login(username, password);
if(storedUsername.equals(username)&& storedPassword.equals(password)){
status = true;
}else{
status = false;
}
}
return status;
}
Thanks! Query6273
Your code does compare every line of the file to the username and password. But at each iteration, you replace the previous value of status with the status of the current line.
So you end up returning the status of the last line.
You need to break out of the loop as soon as you found the user you were looking for. For example:
while (scan.hasNextLine()) {
...
if (storedUsername.equals(username) && storedPassword.equals(password)) {
return true;
}
}
or
// we haven't found the user yet, so status is false
boolean status = false;
while (scan.hasNextLine() && !status) {
...
if (storedUsername.equals(username) && storedPassword.equals(password)) {
status = true;
}
}
return status;
Note that the Scanner should be closed properly. You should use try-with-resources.
I have a textfile as such:
type = "Movie"
year = 2014
Producer = "John"
title = "The Movie"
type = "Magazine"
year = 2013
Writer = "Alfred"
title = "The Magazine"
What I'm trying to do is, first, search the file for the type, in this case "Movie" or "Magazine".
If it's a Movie, store all the values below it, i.e
Set the movie variable to be 2014, Producer to be "John" etc.
If it's a Magazine type, store all the variables below it as well separately.
What I have so far is this:
public static void Parse(String inPath) {
String value;
try {
Scanner sc = new Scanner(new FileInputStream("resources/input.txt"));
while(sc.hasNextLine()) {
String line = sc.nextLine();
if(line.startsWith("type")) {
value = line.substring(8-line.length()-1);
System.out.println(value);
}
}
} catch (FileNotFoundException ex) {
Logger.getLogger(LibrarySearch.class.getName()).log(Level.SEVERE, null, ex);
}
}
However, I'm already having an issue in simply printing out the first type, which is "Movie". My program seems to skip that one, and print out "Magazine" instead.
For this problem solely, is it because the line: line.startsWith("type")is checking if the current line in the file starts with type, but since the actual String called lineis set to the nextline, it skips the first "type"?
Also, what would be the best approach to parsing the actual values (right side of equal sign) below the type "Movie" and "Magazine" respectively?
I recommend you try the following:
BufferedReader reader = new BufferedReader(new FileReader(new File("resources/input.txt")));
String line;
while((line = reader.readLine()) != null) {
if (line.contains("=")) {
String[] bits = line.split("=");
String name = bits[0].trim();
String value = bits[1].trim();
if (name.equals("type")) {
// Make a new object
} else if (name.equals("year")) {
// Store in the current object
}
} else {
// It's a new line, so you should make a new object to store stuff in.
}
}
In your code, the substring looks suspect to me. If you do a split based on the equals sign, then that should be much more resilient.
My problem could be solved if Scanner class had previous() method on it. I am asking this question to know if there are any methods to achieve this functionality.
Input:
a file with contents like
a,1
a,2
a,3
b,1
c,1
c,2
c,3
c,4
d,1
d,2
d,3
e,1
f,1
I need to create a list of all lines that has same alphabet.
try {
Scanner scanner = new Scanner(new File(fileName));
List<String> procList = null;
String line =null;
while (scanner.hasNextLine()){
line = scanner.nextLine();
System.out.println(line);
String[] sParts = line.split(",");
procList = new ArrayList<String>();
procList.add(line);
boolean isSamealpha = true;
while(isSamealpha){
String s1 = scanner.nextLine();
if (s1.contains(sParts[0])){
procList.add(s1);
}else{
isSamealpha = false;
System.out.println(procList);
}
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
I get output like
a,1
[a,1, a,2, a,3]
c,1
[c,1, c,2, c,3, c,4]
d,2
[d,2, d,3]
f,1
[f,1]
As you can see it missed list for b and e. If I has scanner.previous() method, I would have put it in else of second while loop. Because there is no previous method, I am stuck.
Please let me know if there are any methods I can use. I can't use FileUtils.readLines() because its a 3GB file and I don't want to use my java memory to store all the file.
I would suggest reconsidering your algorithm instead. You are missing tokens because your algorithm involves reading ahead to determine when the sequence has broken, yet you aren't collecting that next line of input into the same structures that you are placing "duplicate" entries.
You can solve this without needing to read backwards. If you know that the input is always sorted, just read line by line and keep a reference to the last line (to compare with the current one).
Below is some sample code that should help. (I only typed this; I did no checking.)
Scanner scanner = new Scanner(new File(fileName));
List<String> procList = null;
String line = null;
String previousAlpha = null;
while (scanner.hasNextLine()){
line = scanner.nextLine();
if (previousAlpha == null) {
// very first line in the file
procList = new ArrayList<String>();
procList.add(line);
System.out.println(line);
previousAlpha = line.split(",")[0];
}
else if (line.contains(previousAlpha)) {
// same letter as before
procList.add(line);
}
else {
// new letter, but not the very first
// line
System.out.println(procList);
procList = new ArrayList<String>();
procList.add(line);
System.out.println(line);
previousAlpha = line.split(",")[0];
}
}