Get specific text from a .txt file - java

I want to get information from a script so i used this function
public static HashMap<String, String> getEnvVariables(String scriptFile,String config) {
HashMap<String, String> vars = new HashMap<String, String>();
try {
FileInputStream fstream = new FileInputStream(scriptFile);
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
String strLine;
String var= "if [ \"$1\" = \""+config +"\" ] ; then";
// Read File Line By Line
while ((strLine = br.readLine()) != null) {
// use a Scanner to parse the content of each line
// exclude concatenated variables (export xx:$xx)
if (strLine.startsWith("export") && !strLine.contains("$")) {
strLine = strLine.substring(7);
Scanner scanner = new Scanner(strLine);
scanner.useDelimiter("=");
if (scanner.hasNext()) {
String name = scanner.next();
String value = scanner.next();
System.out.println(name+"="+value);
vars.put(name, value);
}
}
}
However i want to begin reading from a particular line which is
if [ \"$1\" = \""+config +"\" ] ; then
the problem is that when a line begins with a space the program considers that the file have ended !
So how can i fix it and make the program pars to the end of file ?
considering that the line could begin with more thant one space
thx

You may try to trim the irrelevant spaces from every line ?
while ((strLine = br.readLine().trim()) != null) {...}
Edit : don't do that (thanks Joop Eggen!) or you'll have a nice NPE...). Try:
while ((strLine = br.readLine()) != null) {
strLine = strLine.trim();
...
}

Sounds for me like you should use regular expressions (e.g. use the String.matches() method). They also can extract strings or substrings (see: another Stackoverflow article).
There is also an excellent introduction by Lars Vogella about regular expressions in Java. Oracle compiled also a Tutorial/Lesson about that topic.
May be this snippet helps a bit (uses org.apache.commons.io.LineIterator):
public void grepLine(File file, String regex)
{
LineIterator it = FileUtils.lineIterator(file, "UTF-8");
try
{
while (it.hasNext())
{
String line = it.nextLine();
if(line.matches(regex))
{
//...do your stuff
}
}
}
finally
{
LineIterator.closeQuietly(it);
}
}
The regex might be something like (note: havn't checked it - especially the backslashes):
String regex="^\\s*if\\s+\\[\\s+\\\"\\$1\\\" = \\\""+config +"\\\" \\] ; then";

Before all else: leave out DataInputStream, more Java Object specific.
boolean started = false;
while ...
if (!started) {
started = strLine.matches("\\s*...\\s*");
} else {
...
Reg ex \\s* stand for zero or more white-space characters (tab, space).

I found a solution which i share with you .
public static HashMap<String, String> getEnvVariables(String scriptFile ,String config1,String config2) {
HashMap<String, String> vars = new HashMap<String, String>();
BufferedReader br = null;
try {
FileInputStream fstream = new FileInputStream(scriptFile);
br = new BufferedReader(new InputStreamReader(fstream));
String strLine = null;
String stopvar = config2;
String startvar =config1;
String keyword = "set";
do {
if (strLine != null && strLine.contains(startvar)) {
if (strLine.contains(stopvar)) {
return vars;
}
while (strLine != null && !strLine.contains(stopvar)) {
strLine = br.readLine();
if (strLine.trim().startsWith(keyword)&& !strLine.contains("$")) {
strLine = strLine.trim().substring(keyword.length())
.trim();
String[] split = strLine.split("=");
String name = split[0];
String value = split[1];
System.out.println(name + "=" + value);
vars.put(name, value);
}
}
}
} while ((strLine = br.readLine()) != null);
} catch (Exception e) {
Status status = new Status(Status.ERROR, Activator.PLUGIN_ID,
IStatus.ERROR, e.getMessage(), e);
Activator.getDefault().getLog().log(status);
}
return vars;
}
thanks for helping !

Related

Replace defined words in a file with replacements in another file - Java

I have a file (file1.txt) containing:
word word word2 word word1
word2 word word 1
The other file (file2.txt) contains:
word1-replacement1
word2-replacement2
I need a method looking up if the words from file2 are contained in file1 and if they are contained replace those words with the replacement.
I already have following:
BufferedReader br = new BufferedReader(new FileReader("file2.txt"));
BufferedReader br2 = new BufferedReader(new FileReader("file1.txt"));
String line;
String line2;
while ((line = br.readLine()) != null) {
String vars[] = line.split("-");
String varname = vars[0];
String replacement = vars[1];
while ((line2 = br2.readLine()) != null) {
if(line2.contains(varname)) {
line2.replace(varname, replacement);
}
}
}
The problem with this code is, that it just reads only the first line of file1.
The final output should look like:
word word replacement2 word replacement1
replacement2 word replacement1
Thanks for your help :)
I suggest first reading in the second file into Java memory, and storing the data as a key value store in a hashmap. Then, iterate over the lines from the first file, and make any matching replacements.
Map<String, String> map = new HashMap<>();
String line = "";
try (BufferedReader br = new BufferedReader(new FileReader("file2.txt"))) {
while ((line = br.readLine()) != null) {
String[] parts = line.split("-");
map.put(parts[0], parts[1]);
}
}
catch (IOException e) {
// handle exception
}
try (BufferedReader br = new BufferedReader(new FileReader("file1.txt"))) {
while ((line = br.readLine()) != null) {
for (Map.Entry< String, String > entry : map.entrySet()) {
String pattern = "\\b" + entry.getKey() + "\\b";
line = line.replaceAll(pattern, entry.getValue());
// now record the updated line; printed to the console here for demo purposes
System.out.println(line);
}
}
}
catch (IOException e) {
// handle exception
}
Note carefully that I call String#replaceAll above with word boundaries around each term. This matters because, for example, without boundaries the term word1 would match something like aword1term, that is, it would match word1 even as a substring of some other word.
You can start by creating a Map of replacements like so:
public Map<String,String> getReplacements(File file) throws FileNotFoundException {
Map<String, String> replacementMap = new HashMap<>();
Scanner sc = new Scanner(file);
while(sc.hasNextLine()) {
String line = sc.nextLine();
String [] replacement = line.split("-");
String from = replacement[0];
String to = replacement[1];
replacementMap.put(from,to);
}
return replacementMap;
}
And then use the map to replace the words in the other file.

How to remove the duplicate string?

In my code I have two files in my drive those two files have some text and I want to display those string in the console and also remove the repeated string and display the repeated string once rather than displaying it twice.
Code:
public class read {
public static void main(String[] args) {
try{
File file = new File("D:\\file1.txt");
FileReader fileReader = new FileReader(file);
BufferedReader br = new BufferedReader(fileReader);
StringBuffer stringBuffer = new StringBuffer();
String line;
while((line = br.readLine()) != null){
stringBuffer.append(line);
stringBuffer.append("\n");
}
fileReader.close();
System.out.println("Contents of file1:");
String first = stringBuffer.toString();
System.out.println(first);
File file1 = new File("D:\\file2.txt");
FileReader fileReader1 = new FileReader(file1);
BufferedReader br1 = new BufferedReader(fileReader1);
StringBuffer stringBuffer1 = new StringBuffer();
String line1;
while((line1 = br1.readLine()) != null){
stringBuffer1.append(line1);
stringBuffer1.append("\n");
}
fileReader1.close();
System.out.println("Contents of file2:");
String second = stringBuffer1.toString();
System.out.println(second);
System.out.println("answer:");
System.out.println(first+second);
}catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
Output is:
answer:
hi hello
how are you
hi ya
i am fine
But I want to compare both the strings and if the same string repeated then that string should be displayed once.
Output I expect is like this:
answer:
hi hello
how are you
ya
i am fine
Where the "hi" is found in both the strings so that I need to delete the one duplicate string.
How can I do that please help.
Thanks in advance.
You can pass your lines through this method to parse out duplicate words:
// store unique previous words
static Set<String> words = new HashSet<>();
static String removeDuplicateWords(String line) {
StringJoiner sj = new StringJoiner(" ");
// split on whitespace to get distinct words
for (String word : line.split("\\s+")) {
// try to add word to the set
if (words.add(word)) {
// if the word was added (=not seen before), append to the result
sj.add(word);
}
}
return sj.toString();
}

Trying to read in multiple lines of a file into string array depending on what the line starts with then enter into a map

Why do i only get one entry into the map when i run this code.There is thousands of lines in the file im reading in but it only seems to be getting to the first line and stopping?
public class Details {
public Map<String, String> dictionaryWords() throws IOException{
String cvsSplitBy = ",";
Collection<String> words = new TreeSet<String>();
Map<String,String> m = new TreeMap<String,String>();
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("dictionary.csv")));
String line = null;
String [] word = null;
String remove = null;
String nextline = null;
String getAllLines = "-";
while ((line = br.readLine())!= null) {
if (line.startsWith("\"")) {
getAllLines = line;
while((nextline = br.readLine())!= null){
if(!nextline.startsWith("\"")){
getAllLines.concat(nextline);
}else{
}
words.add(getAllLines);
word = getAllLines.split(cvsSplitBy);
remove = word[0].replace('"', '-');
m.put(remove.toLowerCase(),Arrays.toString(word));
}
}else{
}
}
for (String key : m.keySet()) {
System.out.println(key + " " + m.get(key));}
return m;
}
Try the following code
if(!nextline.startsWith("\""))
{
getAllLines = getAllLines.concat(nextline);
}
Don't forget to reassign "getAllLines" to the return value of the .concat() function. Since Strings are immutable, the .concat() function returns a new String object, which you do not assign to anything (therefore it is lost). This leaves you with your original String still stored in "getAllLines" as if the call to .concat() was never made.
Feel Free to use the StringBuilder class and the append method, which will likely be much faster than creating new Strings via .concat() thousands of times.
Also: You do not need blank else{} statements.
In the following part of your code the nextlines (2nd ...) are lost in space. They are saved in the variable nextline and used as a parameter for getAllLines.concat. But the return value of String::concat is not assigned to anything.
...
while((nextline = br.readLine())!= null){
if(!nextline.startsWith("\"")){
getAllLines.concat(nextline);
}else{
...

Store Map entries in file and read those back in

I have declared a map like below and filled this with Value and Keys.
Map<String,List<String>> cat = new HashMap<String,List<String>>();
I can successfully write this to a file like this:
try{
File SubCats = new File("subcats.txt");
FileOutputStream fos=new FileOutputStream(SubCats);
PrintWriter pw = new PrintWriter(fos);
for(Map.Entry<String,List<String>> m :cat.entrySet()) {
pw.println(m.getKey()+"="+m.getValue());
}
pw.flush();
pw.close();
fos.close();
}
My question now is how to read this back into the map from the file. I trying something like this, but do not know how to 'put' the Value and Keys back in.
BufferedReader in = new BufferedReader(new FileReader("subcats.txt"));
String line = "";
while ((line = in.readLine()) != null) {
String parts[] = line.split("\t");
for(Map.Entry<String,List<String>> m :cat.entrySet()) {
(m.putKey(), m.putValue());
}
in.close();
}
Thx.
public Map<String, List<String>> readSubCats() throws IOException {
Map<String, List<String>> ret = new HashMap<String, List<String>>();
BufferedReader in = new BufferedReader(new FileReader("subcats.txt"));
String line = null;
while ((line = in.readLine()) != null) {
int i = line.indexOf("=");
// if i < 0 throw an Exception
ret.put(line.substring(0, i), Arrays.asList(line.substring(i + 2, line.length() - 1).split(",\\t")));
}
in.close();
return ret;
}
This will only work if you don't have any \n and \t in your Strings in the List and no = in the key, other characters are fine.
Note that split expects a regular expression, a tab in regex is like in Java \t, but because \ is the escape character in Java we need to escape itself, which leads \\t. If you want to split by \ then you have to write split("\\\\") because \ is also the escape character in regex.

Replace a String inside a file using java

I have a TXT file in which I'd like to change this String
<!DOCTYPE Publisher
PUBLIC "-//Springer-Verlag//DTD A++ V2.4//EN" "http://devel.springer.de/A++/V2.4/DTD/A++V2.4.dtd">
into this one <!DOCTYPE Publisher> using Java.
I wrote the following function but it seems not to be working.
public void replace() {
try {
File file = new File("/home/zakaria/Bureau/PhD/test2/file.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = "", oldtext = "";
while((line = reader.readLine()) != null) {
oldtext += line + "\n";
}
reader.close();
String newtext = oldtext
.replaceAll("<!DOCTYPE Publisher\nPUBLIC \"-//Springer-Verlag//DTD A++ V2.4//EN\" \"http://devel.springer.de/A++/V2.4/DTD/A++V2.4.dtd\">",
"<!DOCTYPE Publisher>");
FileWriter writer = new FileWriter("/home/zakaria/Bureau/PhD/test2/file.txt");
writer.write(newtext);
writer.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
What did I do wrong?
Try this simple code:
public static void replace() {
try {
File file = new File("resources/abc.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = "", oldtext = "";
boolean found = false;
while ((line = reader.readLine()) != null) {
if (line.trim().startsWith("<!DOCTYPE Publisher")) {
found = true;
}
if (line.trim().endsWith("A++V2.4.dtd\">")) {
oldtext += "<!DOCTYPE Publisher>";
found = false;
continue;
}
if (found) {
continue;
}
oldtext += line + "\n";
}
reader.close();
FileWriter writer = new FileWriter("resources/file.txt");
writer.write(oldtext);
writer.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
You are fortunate to start with that it didn't change anything at all.
Otherwise you'd have lost your original file...
Never modify a file in place!!
Create a temporary file where you write the modified content, and only then rename to your original file.
Also, the string you want to replace is pretty complicated, and you don't want to use .replace() since this will replace all occurrences.
Do like this:
final String quoted
= Pattern.quote("<!DOCTYPE Publisher\nPUBLIC \"-//Springer-Verlag//DTD A++ V2.4//EN\" \"http://devel.springer.de/A++/V2.4/DTD/A++V2.4.dtd\">");
final Pattern pattern = Pattern.compile(quoted);
final Path victim = Paths.get("/home/zakaria/Bureau/PhD/test2/file.txt");
final Path tmpfile = Files.createTempFile("tmp", "foo");
final byte[] content = Files.readAllBytes(victim);
final String s = new String(content, StandardCharsets.UTF_8);
final String replacement = pattern.matcher(s).replaceFirst("<!DOCTYPE Publisher>");
try (
final OutputStream out = Files.newOutputStream(tmpfile);
) {
out.write(replacement.getBytes(StandardCharsets.UTF_8));
out.flush();
}
Files.move(tmpfile, victim);
If the text you want to eliminate is on the second and subsequent lines, as in your demo-input
<!DOCTYPE Publisher
PUBLIC "-//Springer-Verlag//DTD A++ V2.4//EN"
"http://devel.springer.de/A++/V2.4/DTD/A++V2.4.dtd">
and no lines between the first and last in the tag contain a closing >, then you can do the following:
while(more lines to process)
if "<!DOCTYPE Publisher" is not found
read line and output it
else
//This is the first line in a <!DOCTYPE tag
read the line and output it, appending '>' to the end
while the next line does NOT end with a '>'
discard it (don't output it)
Try with this regexp:
String newtext = oldtext.replaceAll(
"<!DOCTYPE Publisher\nPUBLIC \"-\\/\\/Springer-Verlag\\/\\/DTD A[+][+] V2[.]4\\/\\/EN\"[ ]\"http:\\/\\/devel[.]springer[.]de\\/A[+][+]\\/V2[.]4\\/DTD\\/A[+][+]V2[.]4[.]dtd\">", "<!DOCTYPE Publisher>");
The only changes are escaping forward slashes and putting dots and plus signs between square brackets.

Categories

Resources