Suppose we have two files as f1 and f2.
Also suppose that there is a function named comparision(File f1,File f2).
This function will get the two files as arguments and take the first character(word) from f1 and compare it with all the characters in the f2 until the end, picking second ones and doing it until end as first and etc.
My question is: How can I implement this? Do I need to know the EOF ? And if so, how to get it?
Assume that files are plain text (.txt) and every word is in one line.
as an example:
f1:
I
am
new
to
java
f2:
java
is
a
programing
language
Here's the code:
static void comparision(File f, File g) throws Exception
{
Set<String> text = new LinkedHashSet<String>();
BufferedReader br = new BufferedReader(new FileReader(g));
for(String line;(line = br.readLine()) != null;)
text.add(line.trim().toString());
if(text==null)
return;
BufferedReader br = new BufferedReader(new FileReader(f));
String keyword = br.readLine();
if (keyword != null) {
Pattern p = Pattern.compile(keyword, Pattern.CASE_INSENSITIVE);
StringBuffer test = new StringBuffer(text.toString());
matcher = p.matcher(test);
if (!matcher.hitEnd()) {
total++;
if (matcher.find()) {
//do sth
}
}
}
}
edit by jcolebrand
Something to think about, we need program flow that looks like this (psuedocode)
function(file1,file2) throws exceptions{
ArrayList<string> list1, list2; //somebody said we should use an ArrayList ;-)
string readinTempValue = null;
br = BufferedReader(file1) //we are already using a BufferredReader
readinTempValue = br.ReadLine();
//this is a loop structure
while (readinTempValue != null){ //trust me on this one
//we need to get the string into the array list....
//how can we ADD the value to list1
readinTempValue = br.ReadLine(); //trust me on this one
}
br = BufferedReader(file2) //we are already using a BufferredReader
readinTempValue = br.ReadLine();
//this is a loop structure
while (readinTempValue != null){ //trust me on this one
//we need to get the string into the array list....
//how can we ADD the value to list2
readinTempValue = br.ReadLine(); //trust me on this one
}
foreach(value in list1){
foreach(value in list2){
compare value from list 1 to value from list 2
}
}
}
Simple basic algorithm (can be fine tuned based upon WHY you want to compare)
Read the second file and create a HashSet "hs"
for each word "w" in file 1
if(hs.contains(w))
{
w is present in the second file
}
else
{
w is not present in the second file
}
modifications to OP's code
static int comparision(File f, File g) throws Exception
{
int occurences = -1;
Set<String> text = new HashSet<String>();
BufferedReader br = new BufferedReader(new FileReader(g));
String line = br.readLine();
while (line != null)
{
String trimmedLine = line.trim();
if (trimmedLine.length() > 0)
{
text.add(trimmedLine.toString());
}
line = br.readLine();
}
if (text.isEmpty())
{
// file 1 doesn't contain any useful data
return -1;
}
br = new BufferedReader(new FileReader(f));
String keyword = br.readLine();
if (keyword != null)
{
String trimmedKeyword = keyword.trim();
if (trimmedKeyword.length() > 0)
{
if (text.contains(trimmedKeyword))
{
occurences++;
}
}
line = br.readLine();
}
return occurences;
}
Related
I'm writing a code where I've to read current line and next line. If next line contains some string, I need to delete current line.
But when I do it, once it reaches the EOF, it is showing me null pointer exception.
Below is my code.
private static void cleanUpTempFile(File temp) throws IOException {
FileReader fr = new FileReader(temp);
BufferedReader temp_in = new BufferedReader(fr);
String tempStr, tempStr1 = null;
int i = 0;
for (String next, footnotes = temp_in.readLine(); footnotes != null; footnotes = next) {
next = temp_in.readLine();
try {
if (next.contains("pb") && (next != null)) {
tempStr = footnotes;
tempStr1 = tempStr;
tempStr = tempStr1.replace(tempStr1, "");
footnotes = tempStr;
}
} catch (Exception e) {
System.out.println(e);
}
System.out.println(footnotes);
}
temp_in.close();
}
It is throwing me error since when it comes since, when it comes to end, current line is showing last line and next points to next line which is null. How can I sort this.
Also, whenever there is a replace done, and empty line is created, Is there a way that I can stop creating a new line.
I tried adding the below code in my if
tempStr1 = tempStr;
footnotes = tempStr1.replace("\\s", "");
But this doesn't seem working.
Tried with the below code and my console prints null.
private static void cleanUpTempFile(File temp) throws IOException {
FileReader fr = new FileReader(temp);
BufferedReader temp_in = new BufferedReader(fr);
String tempStr, tempStr1 = null;
String footnotes;
while ((footnotes = temp_in.readLine()) != null) {
String next;
while ((next = temp_in.readLine()) != null) {
if (next.contains("pb")) {
tempStr = footnotes;
tempStr1 = tempStr;
tempStr = tempStr1.replace(tempStr1, "");
footnotes = tempStr;
}
}
}
System.out.println(footnotes);
temp_in.close();
}
Thanks.
As suggested by Baldurian you can check this by using Scanner#hasNextLine():
Scanner input = new Scanner(new File(filename));
String prevLine = input.nextLine();
while(input.hasNextLine())
{
String nextLine = input.nextLine();
//do some stuff
prevLine = nextLine;
}
Along with checking if the file exists and appending to it if so you should also have a .hasNextLine() conditional.
I'm writing a program in java to search for a list of words(transaction numbers) in a .txt file. The .txt file can have any number of lines.
List<String> transactionList = new ArrayList<String>(
Arrays.asList("JQ7P00049", "TM7P04797", "RT6P70037");
FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
try {
String readLine = bufferedReader.readLine();
for (String transactionIndex : transactionList) {
if (readLine != null) {
if (readLine.contains(transactionIndex)) {
System.out.println(transactionIndex + ": true");
readLine = bufferedReader.readLine();
} else {
readLine = bufferedReader.readLine();
}
}
}
}
The programs runs fine except if the word is split between two lines, for example:
-------- JQ7P0
0049----------
that's obviously because the bufferedReader reads line by line and does the comparison of search string with the content present in that line.
Is there any way to handle this scenario?
As durron597 mentioned, you weren't looping through the whole file, but here's a solution that assumes the file has at least 2 lines and that a transaction string doesn't span more than 2 lines.
It concatenates each line with the next, and searches for the strings in the concatenated lines. To prevent the same transaction from being printed twice, I added an additional check.
List<String> transactionList = new ArrayList<String>( Arrays.asList("JQ7P00049", "TM7P04797", "RT6P70037") );
FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
try {
// Search the first line
String lastLine = bufferedReader.readLine();
for (String transactionIndex : transactionList) {
if (lastLine.contains(transactionIndex)) {
System.out.println(transactionIndex + ": true");
}
}
String currentLine = null;
// Search the remaining lines
while((currentLine=bufferedReader.readLine()) != null) {
String combined = lastLine + currentLine;
for (String transactionIndex : transactionList) {
if (currentLine.contains(transactionIndex) || (!lastLine.contains(transactionIndex) && combined.contains(transactionIndex))) {
System.out.println(transactionIndex + ": true");
}
}
lastLine = currentLine;
}
} catch ( Exception e ) {
System.out.println( e.getClass().getSimpleName() + ": " + e.getMessage() );
} finally {
bufferedReader.close();
}
This program has a second problem: You aren't going to read all the lines in longer files, because you have no loop that will loop through all the lines in the file.
That said, you can do this by reading two lines at once, and merging them together.
Here's a complete program:
private static final List<String> transactionList = new ArrayList<String>(Arrays.asList(
"JQ7P00049", "TM7P04797", "RT6P70037"));
public static void main(String[] args) throws Exception {
String filePath = "test.txt";
FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
try {
String firstLine = bufferedReader.readLine();
String secondLine = bufferedReader.readLine();
if (secondLine == null) {
checkLine(firstLine);
}
do {
String combinedLine = firstLine + secondLine;
checkLine(combinedLine);
firstLine = secondLine;
} while ((secondLine = bufferedReader.readLine()) != null);
} finally {
}
}
private static void checkLine(String combinedLine) {
for (Iterator<String> iterator = transactionList.iterator(); iterator.hasNext();) {
String transactionIndex = iterator.next();
if (combinedLine.contains(transactionIndex)) {
System.out.println(transactionIndex + ": true");
iterator.remove();
}
}
}
Your code seems to not properly read the file, but rather reads as many lines as you have transaction numbers you're looking for. Assuming that this is not what you want, I have corrected it.
Also, I assume that an transaction number can span AT MOST two lines.
List<String> transactionList = new ArrayList<String>(
Arrays.asList("JQ7P00049", "TM7P04797", "RT6P70037"));
FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String[] lastLines = {"",""};
try {
String readLine;
while((readLine = bufferedReader.readLine()) != null) {
lastLines[0] = lastLines[1];
lastLines[1] = readLine;
String combinedLastLines;
combinedLastLines = lastLines[0] + lastLines[1];
for (String transactionIndex : transactionList) {
if (combinedLastLines.contains(transactionIndex) && !lastLines[0].contains(transactionIndex)) {
System.out.println(transactionIndex + ": true");
}
}
}
}
The general idea is to always combine two lines, and look whether the transaction number is in there. Let's have a look at the code:
String[] lastLines = {"",""};
This line defines an array which we will use to store the two most recently read lines.
while((readLine = bufferedReader.readLine()) != null) {
This snippet reads as many lines as there are in your text file.
lastLines[0] = lastLines[1];
lastLines[1] = readLine;
String combinedLastLines;
combinedLastLines = lastLines[0] + lastLines[1];
This code is responsible for replacing the oldest line in the array, and push the currently readLine into the array. Those last two lines are then combined to one String!
if (combinedLastLines.contains(transactionIndex) && !lastLines[0].contains(transactionIndex)) {
Here we are searching the combined lines for the transaction numbers. But: when a transaction number is not spanning multiple lines, we might accidently find it twice. Therefore, the second check is for ensuring we did not find the transaction before.
Hope this is what you're looking for!
I am having difficulties with a program that I have been working on all day. I am trying to read a text file and read each line one at a time. Take that line and make an arraylist of the words of the line. then using the index of the arraylist define terms with it.
public class PCB {
public static void main(String arg[]) {
read();
}
public static ArrayList read() {
BufferedReader inputStream = null;
ArrayList<String> tokens = new ArrayList<String>();
try {
inputStream = new BufferedReader(new FileReader("processes1.txt"));
String l;
while ((l = inputStream.readLine()) != null) {
Scanner tokenize = new Scanner(l);
while (tokenize.hasNext()) {
tokens.add(tokenize.next());
}
return tokens;
}
} catch (IOException ioe) {
ArrayList<String> nothing = new ArrayList<String>();
nothing.add("error1");
System.out.println("error");
//return nothing;
}
return tokens;
}
}
The error I am getting is it only reads the first line. What am I doing wrong?
Thank you so much in advance
You have "return tokens;" in your while loop. Seems like that early return would effectively cut off processing on the first line.
Try changing your loop to the following. Note how I moved the return statement.
while ((l = inputStream.readLine()) != null) {
Scanner tokenize = new Scanner(l);
while (tokenize.hasNext()) {
tokens.add(tokenize.next());
}
}
return tokens; // <-- outside the loop
Edit: If you want to read the entire file and store the tokens of each line in a seperate array, then you could create an ArrayList of ArrayList.
public static ArrayList<ArrayList<String>> tokenizeFile(string filename) {
BufferedReader inputStream = new BufferedReader(new FileReader(filename));
ArrayList<ArrayList<String>> lines = new ArrayList<ArrayList<String>>();
while (true) {
String line = inputStream.readLine();
if (line == null) break;
ArrayList<String> tokens = new ArrayList<String>();
Scanner tokenizer = new Scanner(line);
while (tokenizer.hasNext()) {
tokens.add(tokenizer.next());
}
lines.Add(tokens);
}
return lines;
}
Note: My Java is rusty.
Simplify to this ...
String l;
while ((l = inputStream.readLine()) != null) {
tokens.addAll(Arrays.asList(l.split(" ")));
}
... creates a list of all tokens on all lines in the file (if that is what you want).
I want map my object from text file, the text file contents are like this :
~
attribute1value
attribute2value
attribute3value
attribute4value
attribute5value
attribute6value
~
attribute1value
attribute2value
attribute3value
attribute4value
attribute5value
attribute6value
...continued same
So for each 5 attributes I want to create new object and map those 6 properties to it(that is not issue), the issue is how can I distinguish lines while reading, how can I get the first group, second group etc . thank you
I suggest using a 3rd-party utility such as Flatworm to handle this for you.
Adapted from here, and assuming there are always 6 properties per object:
You can use java.io.BufferedReader to read a file line by line.
BufferedReader reader = new BufferedReader(new FileReader("/path/to/file.txt"));
String line = null;
int count = 0;
MyObject obj = null;
while ((line = reader.readLine()) != null) {
if(obj == null) obj = new MyObject();
if(count <= 6) {
switch(count) {
case 0: // ignore: handles '~'
break;
case 1: // assign value of line to first property, like:
obj.prop1 = line;
break;
// etc up to case 6
}
count++;
} else {
// here, store object somewhere, then...
obj = null;
count = 0;
}
}
Here is a more flexible approach. We can specify a custom (single-line) delimiter, no delimiter is actually needed at the beginning or at the end of the file (but can be given), the number of lines of a record is flexible. The data is parsed into a simple model which can be used to validate data and create the final objects.
private String recordDelimiter = "~";
public static List<List<String>> parse(Reader reader) {
List<List<String>> result = new ArrayList<List<String>>();
List<String> record = new ArrayList<String>();
boolean isFirstLine = true;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.length() == 0) {
continue; // we skip empty lines
}
if (delimiter.equals(line.trim()) {
if (!isFirstLine) {
result.add(record);
record = new ArrayList<String>();
} else {
isFirstLine = false; // we ignore a delimiter in the first line.
}
continue;
}
record.add(line);
isFirstLine = false;
}
if (!result.contains(record))
result.add(record); // in case the last line is not a separator
return result;
}
Primitive code, no exception handling, requires 100% perfect file structure and file which ends in the record delimiter character '~'.
Gives you a start though.
public class Record {
private String field1 = null;
private String field2 = null;
private String field3 = null;
private String field4 = null;
private String field5 = null;
private String field6 = null;
private void read(DataInputStream din) throws IOException, ClassNotFoundException {
BufferedReader reader = new BufferedReader(new InputStreamReader(din));
field1 = reader.readLine();
field2 = reader.readLine();
field3 = reader.readLine();
field4 = reader.readLine();
field5 = reader.readLine();
field6 = reader.readLine();
reader.readLine(); // Skip separator line "~".
}
private static void main(String[] args) throws IOException, ClassNotFoundException {
FileInputStream fin = new FileInputStream("C:\\file.dat");
DataInputStream din = new DataInputStream(fin);
Collection<Record> records = new LinkedList<Record>();
while(0 < din.available()) {
Record record = new Record();
record.read(din);
records.add(record);
}
}
}
I am loading text file contents to GUI using this code:
try {
BufferedReader br = new BufferedReader(new FileReader ("text.txt"));
String line;
while ((line = br.readLine()) != null) {
if (line.contains("TITLE")) {
jTextField2.setText(line.substring(11, 59));
}
}
in.close();
} catch (Exception e) {
}
Then contents of text.txt file:
JOURNAL journal name A12340001
TITLE Sound, mobility and landscapes of exhibition: radio-guided A12340002
tours at the Science Museum A12340003
AUTHOR authors name A12340004
On jTextField2 I am getting this line: "Sound, mobility and landscapes of exhibition: radio-guided".
The problem is I don't know how to get to jTextField2 the string of next line "tours at the Science Museum".
I would like to ask how can I get both line on jTextField2 i.e. "Sound, mobility and landscapes of exhibition: radio-guided tours at the Science Museum"?
Thank you in advance for any help.
If you are using Java 8 and assuming that the columns have a fixed number of characters, you could something like this:
public static void main(String args[]) throws IOException {
Map<String, String> sections = new HashMap<>();
List<String> content = (List<String>)Files.lines(Paths.get("files/input.txt")).collect(Collectors.toList());
String lastKey = "";
for(String s : content){
String k = s.substring(0, 10).trim();
String v = s.substring(10, s.length()-9).trim();
if(k.equals(""))
k=lastKey;
sections.merge(k, v, String::concat);
lastKey=k;
}
System.out.println(sections.get("TITLE"));
}
The first column is the key. When the keys does not exist, the last key is used. A Map is used to store the keys and the values. When the key already exist, the value is merged with the existing one by concatenation.
This code outputs the expected String: Sound, mobility and landscapes of exhibition: radio-guidedtours at the Science Museum.
EDIT: For Java 7
public static void main(String args[]) {
Map<String, String> sections = new HashMap<>();
String s = "", lastKey="";
try (BufferedReader br = new BufferedReader(new FileReader("files/input.txt"))) {
while ((s = br.readLine()) != null) {
String k = s.substring(0, 10).trim();
String v = s.substring(10, s.length() - 9).trim();
if (k.equals(""))
k = lastKey;
if(sections.containsKey(k))
v = sections.get(k) + v;
sections.put(k,v);
lastKey = k;
}
} catch (IOException e) {
System.err.println("The file could not be found or read");
}
System.out.println(sections.get("TITLE"));
}
Why not create a MyFile class that does the parsing for you, storing key-value-pairs in a Map<String, String>, which you can then access. This will make your code more readable and will be easier to maintain.
Something like the following:
public class MyFile {
private Map<String, String> map;
private String fileName;
public MyFile(String fileName) {
this.map = new HashMap<>();
this.fileName = fileName;
}
public void parse() throws IOException {
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line = br.readLine();
String key = "";
while (line != null) {
//Only update key if the line starts with non-whitespace
key = line.startsWith(" ") ? title : line.substring(0, line.indexOf(" ")).trim();
//If the key is contained in the map, append to the value, otherwise insert a new value
map.put(key, map.get(key) == null ? line.substring(line.indexOf(" "), 59).trim() : map.get(key) + line.substring(line.indexOf(" "), 59).trim());
line = br.readLine();
}
}
public String getEntry(String key) {
return map.get(key);
}
public String toString() {
StringBuilder sb = new StringBuilder();
for (Entry entry:map.entrySet()) {
sb.append(entry.getKey()).append(" : ").append(entry.getValue()).append("\n");
}
return sb.toString();
}
}
This will parse the entire file first. The expected format of the file is:
0 ... 59
[KEY][WHITE SPACE][VALUE]
0 ... 59
[WHITE SPACE][VALUE TO APPEND TO PREVIOUS KEY]
This allows for variable length keys.
Allowing you to handle exceptions separately, and then easily reference the contents of the file like so:
MyFile journalFile = new MyFile("text.txt");
try {
journalFile.parse();
} catch (IOException e) {
System.err.println("Malformed file");
e.printStackTrace();
}
jTextField2.setText(journalFile.getEntry("TITLE"));
An empty (all spaces) first column indicates that a line is the continuation of the previous one. So you can buffer the lines and repeatedly concatenate them, until you get a non-empty first column, and then write/print the whole line.
try {
BufferedReader br = new BufferedReader(new FileReader("text.txt")) ;
String line ;
String fullTitle = "" ;
while ((line = br.readLine()) != null) {
//extract the fields from the line
String heading = line.substring(0, 9) ;
String titleLine = line.substring(10, 69) ;
//does not select on "TITLE", prints all alines
if(heading.equals(" ")) {
fullTitle = fullTitle + titleLine ;
} else {
System.out.println(fullTitle) ;
fullTitle = titleLine ;
}
}
System.out.println(fullTitle) ; //flush the last buffered line
} catch (Exception e) {
System.out.println(e) ;
}
you can do this
First of all read the entire file into a string object.
then get the indexes of the TITLE and AUTHOR
like int start=str.indexOf("TITLE"); and int end=str.indexOf("AUTHOR");
then add the length of TITLE into start index start+="TITLE".length();
and subtract the length of AUTHOR from end index end-="AUTHOR".length();
at last you have the start and end index of text that you want.
so get the text like.
String title=str.subString(start,end);