Store Map entries in file and read those back in - java

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.

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();
}

Can not acquire value from Hashtable

I wrote the following Java code,
try {
String str = "";
Hashtable< String, String> table = new Hashtable< String, String>();
fis = new FileInputStream("C:\\Users\\Dave\\Desktop\\station.txt");// FileInputStream
isr = new InputStreamReader(fis);
br = new BufferedReader(isr);
String str1 = "012649-99999";
String str2 = "012650-99999";
while ((str = br.readLine()) != null) {
String[] record = str.split("\t");
table.put(record[0], record[1]);
}
String stationName1 = table.get(str1);
String stationName2 = table.get(str2);
} catch(...)
Snd the content of station.txt is as follows:
012649-99999 SIHCCAJAVRI
012650-99999 TRNSET-HANSMOEN
When I run the program, the stationName1 is always null, and the stationName2 can get value 012650-99999. Who can tell me why this happen? Thank you in advance!
#matt: Yes, that's right, when I changed the encoding from 'UTF-8' to 'ANSI', it worked, stationName1 can get value, but why 'UTF-8' does not work for this situation? I always use that format.
The problem is your text file doesn't contain any \t character. There are multiple spaces. The correct way is to use \\s+, that matches mutliple whitespaces.
String[] record = str.split("\\s+");
Moreover Hashtable is obsolete. There is HashMap<> instead now. Here is the full code working for me. I have tested it:
String str;
HashMap<String, String> table = new HashMap<>();
FileInputStream fis = new FileInputStream("station.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String str1 = "012649-99999";
String str2 = "012650-99999";
while ((str = br.readLine()) != null) {
String[] record = str.split("\\s+");
table.put(record[0], record[1]);
}
System.out.println(table.get(str1));
System.out.println(table.get(str2));
Could you please replace your following line:
String[] record = str.split("\t");
by following line:
String[] record = str.split("[\\s]+");
and see the result?
Your working solution is here:-
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Hashtable;
public class Test {
public static void main(String[] args) {
try {
String str = "";
Hashtable< String, String> table = new Hashtable< String, String>();
FileInputStream fis = new FileInputStream("C:\\Users\\Dave\\Desktop\\station.txt");// FileInputStream
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String str1 = "012649-99999";
String str2 = "012650-99999";
while ((str = br.readLine()) != null) {
System.out.println(str);
String[] record = str.split("[\\s]+");
table.put(record[0], record[1]);
}
br.close();
String stationName1 = table.get(str1);
String stationName2 = table.get(str2);
System.out.println("stationName1:"+stationName1);//
System.out.println("stationName2:"+stationName2);//
} catch(Exception e){
System.out.println(e);
}
}
}
If you're sure the file contains TAB space, the correct way to match will be as follows.
String[] record = str.split("\\t");
The argument to split() is a regex and the regex for TAB space is \t which as a Java String will be "\\t".
Also, don't use Hashtable, use HashMap instead as explained in the other answer.

StringTokenizer multiple lines

I have two files, called "ride.in" and "ride.out". The "ride.in" file contains two lines, one containing the string "COMBO" and the other line containing the string "ADEFGA". As I said, each string is on separate lines, so "COMBO" is on the first line, while "ADEFGA" is on the second line in the "ride.in" file.
Here is my code:
public static void main(String[] args) throws IOException {
File in = new File("ride.in");
File out = new File("ride.out");
String line;
in.createNewFile();
out.createNewFile();
BufferedReader br = new BufferedReader(new FileReader(in));
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(out)));
while ((line = br.readLine()) != null) {
StringTokenizer st = new StringTokenizer(line);
String sam =st.nextToken();
}
pw.close();
}
}
I want to assign COMBO as one token and ADEFGA as another token, but in this code, both COMBO and ADEFGA are assigned to the sam string. How do I assign COMBO to one string, and ADEFGA to another string?
You can read each line from the file into a List<String>:
List<String> words = Files.readAllLines(new File("ride.in").toPath(), Charset.defaultCharset() );
Alternatively, you can use Fileutils:
List<String> words = FileUtils.readLines(new File("ride.in"), "utf-8");
words should now contain:
['COMBO', 'ADEFGA']
Note: Adjust your ride.in's file path accordingly
You can't create variable number of variables.
Create a arraylist of string.
Change
while ((line = br.readLine()) != null) {
StringTokenizer st = new StringTokenizer(line);
String sam =st.nextToken();
}
to
List<String> myList = new ArrayList<String>();
while ((line = br.readLine()) != null) {
StringTokenizer st = new StringTokenizer(line);
myList.add(st.nextToken());
}
Now myList.get(0) will have "COMBO" and myList.get(1) will have "ADEFGA"

Get specific text from a .txt file

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 !

Categories

Resources