I am going through Mooc.fi Java course and I can't figure how not to write String into file if the file already contains it. I tried only with one String and tried without " " (empty space), and without another string, but still it adds the string even when the file already contains it.
And translate() method doesn't find/return whole line in which it found the given word.
public class main {
public static void main(String[] args) throws Exception {
MindfulDictionary dict = new MindfulDictionary();
dict.add("apina", "monkey");
dict.add("banaani", "banana");
dict.add("apina", "apfe");
System.out.println( dict.translate("apina") );
System.out.println( dict.translate("monkey") );
System.out.println( dict.translate("programming") );
System.out.println( dict.translate("banana") );
}
}
public class MindfulDictionary {
File file;
FileWriter writer;
Scanner imeskanera;
public MindfulDictionary() throws Exception {
this.file = new File("C:\\Users\\USER\\Desktop\\test.txt");
this.imeskanera = new Scanner(this.file, "UTF-8");
}
public void add(String word, String translation) throws Exception {
boolean found = false;
while(this.imeskanera.hasNextLine()) {
String lineFromFile = this.imeskanera.nextLine();
if(word.contains(lineFromFile)) {
found = true;
break;
}
}
if(!found) {
this.writer = new FileWriter(this.file,true);
this.writer.write(word +" " + translation +"\n");
this.writer.close();
}
}
public String translate(String word) throws Exception {
String line = null;
while(this.imeskanera.hasNextLine()) {
String data = this.imeskanera.nextLine();
if(data.contains(word)) {
line = data;
break;
}
}
return line;
}
}
The problem is that your Scanner object has already been consumed by the add() method. You need to reopen the input stream in order to read the contents of the file. If you add
this.imeskanera = new Scanner(this.file, "UTF-8");
At the beginning of the translate() method, it should word. Which basically tell you that there is no need for Scanner to be a global field. Use it locally in each method. This is how I have explain the concept of file streams in the past:
Think about file streams (for reading and writing) logically. You
cannot allow for such a stream to be "circular". Otherwise, when you
try to get the "next line", there will always be a next line and you
will never be able to stop reading (or writing). The stream is
consumed when it reach the end, and once that is done, to go back to
the beginning of the stream, you will need to open a new one; not
reuse the old one.
I thought I needed to add this explanation even after the answer was accepted because I know new developer struggle with this concept and it because of that, it is necessary to explain it in detail.
With that said, your MindfulDictionary class should look like this:
public class MindfulDictionary {
File file;
FileWriter writer;
// Scanner imeskanera;
public MindfulDictionary() throws Exception {
this.file = new File("test.txt"); // I changed the path to the file to make it work for me. You can change it back if you want to.
file.createNewFile();
}
public void add(String word, String translation) throws Exception {
Scanner imeskanera = new Scanner(this.file, "UTF-8");
boolean found = false;
while (imeskanera.hasNextLine()) {
String lineFromFile = imeskanera.nextLine();
if (word.contains(lineFromFile)) {
found = true;
break;
}
}
if (!found) {
this.writer = new FileWriter(this.file, true);
this.writer.write(word + " " + translation + "\n");
this.writer.close();
}
imeskanera.close();
}
public String translate(String word) throws Exception {
Scanner imeskanera = new Scanner(this.file, "UTF-8");
String line = null;
while (imeskanera.hasNextLine()) {
String data = imeskanera.nextLine();
if (data.contains(word)) {
line = data;
break;
}
}
imeskanera.close();
return line;
}
}
I ran your code with my modifications and now the output is
apina monkey
apina monkey
null
banaani banana
In addition to the Scanner issue mentioned by the answer of #hfontanez, following changes.
if (word.contains(lineFromFile))
This checks if the first word contains the line, this is not true. The file contains the first word and translation. so this can be changed to
if (lineFromFile.contains(word))
as #ghostCat mentioned searching the key(word) can be refactored. Code with these changes.
public class MindfulDictionary {
File file;
FileWriter writer;
// Scanner imeskanera;
public MindfulDictionary() throws Exception {
this.file = new File("test.txt");
file.createNewFile();
}
public void add(String word, String translation) throws Exception {
if (get(word) == null) {
this.writer = new FileWriter(this.file, true);
this.writer.write(word + " " + translation + "\n");
System.out.println("Out>>:"+word + " " + translation + "\n");
this.writer.close();
}
}
private String get(String word) throws Exception {
Scanner imeskanera = new Scanner(this.file, "UTF-8");
boolean found = false;
String retStr= null;
while (imeskanera.hasNextLine()) {
String lineFromFile = imeskanera.nextLine();
if (lineFromFile.contains(word)) {
found = true;
retStr=lineFromFile;
break;
}
}
imeskanera.close();
return(retStr);
}
public String translate(String word) throws Exception {
return get(word);
}
public static void main(String[] args) throws Exception {
MindfulDictionary dict = new MindfulDictionary();
dict.add("apina", "monkey");
dict.add("apina", "monkey");
dict.add("banaani", "banana");
dict.add("apina", "apfe");
System.out.println( dict.translate("apina") );
System.out.println( dict.translate("monkey") );
System.out.println( dict.translate("programming") );
System.out.println( dict.translate("banana") );
}
}
Related
I am trying to open a csv file using openCSV, iterate over every column and if the userID is different write a new JavaBean pair at the end of the file.
The problem is that the reader only checks the first column of my file and not the whole file. While created, the file contains only a header and nothing else. The program will check every column and if the sudoID is different it will write it to the file. If the sudoID in the first line is equal to the the one imported from my main class it will recognise it and not write it. But if this -same- sudoID is in the second row it will not recognise it and will write it again.
For instance, if my CSV looks like this it will work:
"Patient_id Pseudo_ID",
"32415","PAT106663926"
If it looks like this it will re-write the sudoID:
"Patient_id Pseudo_ID",
"32416","PAT104958880"
"32415","PAT106663926"
Thanks!
My Code:
public class CSVConnection {
#SuppressWarnings({ "deprecation", "resource", "rawtypes", "unchecked" })
public String getID(String sID,String pseudoID) throws IOException, CsvDataTypeMismatchException, CsvRequiredFieldEmptyException{
try {
CsvToBean csv = new CsvToBean();
String csvFilename = "CsvFile.csv";
Writer writer= new FileWriter(csvFilename,true);
CSVReader csvReader = new CSVReader(new FileReader(csvFilename),',','"',1);
ColumnPositionMappingStrategy strategy = new ColumnPositionMappingStrategy();
strategy.setType(PatientCSV.class);
String[] columns = new String[] {"patID","pseudoID"};
strategy.setColumnMapping(columns);
//Set column mapping strategy
StatefulBeanToCsv<PatientCSV> bc = new StatefulBeanToCsvBuilder<PatientCSV>(writer).withMappingStrategy(strategy).build();
List patList = csv.parse(strategy, csvReader);
for (Object patObj : patList) {
PatientCSV pat = (PatientCSV) patObj;
if(((PatientCSV) patObj).getPatID().equals(sID)){
return pat.getPseudoID();
}
else
{
PatientCSV pat1 = new PatientCSV();
pat1.setPatID(sID);
pat1.setPseudoID(pseudoID);
patList.add(pat1);
/*Find a way to import it to the CSV*/
bc.write(pat1);
writer.close();
return pseudoID;
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static void main(String [] args) throws IOException, CsvDataTypeMismatchException, CsvRequiredFieldEmptyException{
CSVConnection obj = new CSVConnection();
String sID="32415";
String pseudoID="PAT101830150";
obj.getID(sID,pseudoID);
}
}
and the Java Bean :
public class PatientCSV {
private String patID;
private String pseudoID;
public String getPatID() {
return patID;
}
public void setPatID(String patID) {
this.patID = patID;
}
public String getPseudoID() {
return pseudoID;
}
public void setPseudoID(String pseudoID) {
this.pseudoID = pseudoID;
}
public PatientCSV(String patID, String pseudoID) {
super();
this.patID = patID;
this.pseudoID = pseudoID;
}
public PatientCSV() {
super();
// TODO Auto-generated constructor stub
}
public String toString()
{
return "Patient [id=" + patID + ", pseudoID=" + pseudoID + "]";
}
}
Lets inspect your for loop
for (Object patObj : patList) {
PatientCSV pat = (PatientCSV) patObj;
if(((PatientCSV) patObj).getPatID().equals(sID)){
return pat.getPseudoID();
}
else
{
PatientCSV pat1 = new PatientCSV();
pat1.setPatID(sID);
pat1.setPseudoID(pseudoID);
patList.add(pat1);
/*Find a way to import it to the CSV*/
bc.write(pat1);
writer.close();
return pseudoID;
}
}
So in the case you mention it is not working as expected, meaning that the line that matches your input is the second line:
"Patient_id Pseudo_ID",
"32416","PAT104958880"
"32415","PAT106663926"
So you call: getID("32415", "PAT106663926")
What happens in your loop is:
You take the first element of your csv patients, the one with id: 32416,
check if it matches with the id given as input to your method, 32415.
It does not match so it goes to the else part. There it creates the new patient (with the same patID and pseudoID as the 2nd row of your csv) and stores it in the file.
So by now you should have 2 entries in your csv with the same data "32415","PAT106663926".
I think that this is the error, in your for loop you should check against all entries if there is a match, and then create the patient and store it to the csv.
An example:
PatientCSV foundPatient = null;
for (Object patObj : patList) {
PatientCSV pat = (PatientCSV) patObj;
if(((PatientCSV) patObj).getPatID().equals(sID)){
foundPatient = pat;
}
}
if (foundPatient == null) {
foundPatient = new PatientCSV();
foundPatient.setPatID(sID);
foundPatient.setPseudoID(pseudoID);
patList.add(foundPatient);
/*Find a way to import it to the CSV*/
bc.write(foundPatient);
writer.close();
}
return foundPatient.getPseudoID();
P.S. The above example is written very quickly, just to give you the idea what needs to be done.
I've compiled and debugged my program, but there is no output. I suspect an issue passing from BufferedReader to the array method, but I'm not good enough with java to know what it is or how to fix it... Please help! :)
public class Viennaproj {
private String[] names;
private int longth;
//private String [] output;
public Viennaproj(int length, String line) throws IOException
{
this.longth = length;
this.names = new String[length];
String file = "names.txt";
processFile("names.txt",5);
sortNames();
}
public void processFile (String file, int x) throws IOException, FileNotFoundException{
BufferedReader reader = null;
try {
//File file = new File("names.txt");
reader = new BufferedReader(new FileReader(file));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void sortNames()
{
int counter = 0;
int[] lengths = new int[longth];
for( String name : names)
{
lengths[counter] = name.length();
counter++;
}
for (int k = 0; k<longth; k++)
{
int counter2 = k+1;
while (lengths[counter2]<lengths[k]){
String temp2;
int temp;
temp = lengths[counter2];
temp2 = names[counter2];
lengths[counter2] = lengths[k];
names[counter2] = names[k];
lengths[k] = temp;
names[k] = temp2;
counter2++;
}
}
}
public String toString()
{
String output = new String();
for(String name: names)
{
output = name + "/n" + output;
}
return output;
}
public static void main(String[] args)
{
String output = new String ();
output= output.toString();
System.out.println(output+"");
}
}
In Java, the public static void main(String[] args) method is the starting point of the application.
You should create an object of Viennaproj in your main method. Looking at your implementation, just creating an object of Viennaproj will fix your code.
Your main method should look like below
public static void main(String[] args) throws IOException
{
Viennaproj viennaproj = new Viennaproj(5, "Sample Line");
String output= viennaproj.toString();
System.out.println(output);
}
And, if you are getting a FileNotFound exception when you execute this, it means that java is not able to find the file.
You must provide complete file path of your file to avoid that issue. (eg: "C:/test/input.txt")
the content of my file is the following :
nellkb:company_dc
rdfs:label "dC" "WASHINGTON" , "Washington" ;
skos:prefLabel "www.wikipedia.com" .
nellkb:politicsblog_quami_ekta
rdfs:label "Quami Ekta" ;
skos:prefLabel "Quami Ekta" .
nellkb:female_ramendra_kumar
rdfs:label "Ramendra Kumar" ;
skos:prefLabel "Ramendra Kumar" .
i need to split my file at the delimiter '.' and save what we have before it in a string. How can i do that ? i tried the following but it does not work
try {
String sCurrentLine = null;
int i = 0;
br = new BufferedReader(new FileReader(rdfInstanceFile));
while ((sCurrentLine = br.readLine()) != null) {
splitted = sCurrentLine.split(".");
}
} catch (IOException e) {
e.printStackTrace();
}
USE the Scanner class. This scenario is perfect for it. All you need to do is specify the '\\.' delimiter.
There is no need to build a string AND THEN split it...
import java.io.InputStream;
import java.util.Scanner;
public class ScanFile {
public static void main(String[] args) {
try {
InputStream is = ScanFile.class.getClassLoader().getResourceAsStream("resources/foo.txt");
Scanner scan = new Scanner(is);
scan.useDelimiter("\\.[\r\n]+"); // Tokenize at dots (.) followed by CR/LF.
int i = 1;
while (scan.hasNext()) {
String line = scan.next().trim();
System.out.printf("Line #%d%n-------%n%n%s%n%n", i++, line);
}
scan.close();
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Output
Line #1
-------
nellkb:company_dc
rdfs:label "dC" "WASHINGTON" , "Washington" ;
skos:prefLabel "WASHINGTON"
Line #2
-------
nellkb:politicsblog_quami_ekta
rdfs:label "Quami Ekta" ;
skos:prefLabel "Quami Ekta"
Line #3
-------
nellkb:female_ramendra_kumar
rdfs:label "Ramendra Kumar" ;
skos:prefLabel "Ramendra Kumar"
Additional Information
useDelimiter
public Scanner useDelimiter(String pattern)
Sets this scanner's delimiting pattern to a pattern constructed from the specified String.
An invocation of this method of the form useDelimiter(pattern) behaves in exactly the same way as the invocation useDelimiter(Pattern.compile(pattern)).
Invoking the reset() method will set the scanner's delimiter to the default.
Parameters:
pattern - A string specifying a delimiting pattern
Returns:
this scanner
The Scanner constructor takes six (6) different types of objects: File, InputStream, Path, Readable, ReadableByteChannel, and String.
// Constructs a new Scanner that produces values scanned from the specified file.
Scanner(File source)
// Constructs a new Scanner that produces values scanned from the specified file.
Scanner(File source, String charsetName)
// Constructs a new Scanner that produces values scanned from the specified input stream.
Scanner(InputStream source)
// Constructs a new Scanner that produces values scanned from the specified input stream.
Scanner(InputStream source, String charsetName)
// Constructs a new Scanner that produces values scanned from the specified file.
Scanner(Path source)
// Constructs a new Scanner that produces values scanned from the specified file.
Scanner(Path source, String charsetName)
// Constructs a new Scanner that produces values scanned from the specified source.
Scanner(Readable source)
// Constructs a new Scanner that produces values scanned from the specified channel.
Scanner(ReadableByteChannel source)
// Constructs a new Scanner that produces values scanned from the specified channel.
Scanner(ReadableByteChannel source, String charsetName)
// Constructs a new Scanner that produces values scanned from the specified string.
Scanner(String source)
Advanced Solution
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class ScanFile {
private static ClassLoader loader = ScanFile.class.getClassLoader();
private static interface LineProcessor {
void process(String line);
}
private static interface Reader<T> {
T read(String resource, String delimiter) throws IOException;
void flush();
}
private abstract static class FileScanner<T> implements Reader<T> {
private LineProcessor processor;
public void setProcessor(LineProcessor processor) {
this.processor = processor;
}
public T read(Scanner scan, String delimiter, boolean close) throws IOException {
scan.useDelimiter(delimiter);
while (scan.hasNext()) {
processor.process(scan.next().trim());
}
if (close) {
scan.close();
}
return null;
}
public T read(InputStream is, String delimiter, boolean close) throws IOException {
T t = read(new Scanner(is), delimiter, true);
if (close) {
is.close();
}
return t;
}
public T read(String resource, String delimiter) throws IOException {
return read(loader.getResourceAsStream("resources/" + resource), delimiter, true);
}
}
public static class FileTokenizer extends FileScanner<List<String>> {
private List<String> tokens;
public List<String> getTokens() {
return tokens;
}
public FileTokenizer() {
super();
tokens = new ArrayList<String>();
setProcessor(new LineProcessor() {
#Override
public void process(String token) {
tokens.add(token);
}
});
}
public List<String> read(Scanner scan, String delimiter, boolean close) throws IOException {
super.read(scan, delimiter, close);
return tokens;
}
#Override
public void flush() {
tokens.clear();
}
}
public static void main(String[] args) {
try {
FileTokenizer scanner = new FileTokenizer();
List<String> items = scanner.read("foo.txt", "\\.[\r\n]+");
for (int i = 0; i < items.size(); i++) {
System.out.printf("Line #%d%n-------%n%n%s%n%n", i + 1, items.get(i));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
First read the contents of the file into a string, split the string and save it in a string array.
try {
String sCurrentLine = "";
StringBuilder content = new StringBuilder();
String splitted[]= null;
int i = 0;
br = new BufferedReader(new FileReader(rdfInstanceFile));
while ((sCurrentLine = br.readLine()) != null) {
content.append(sCurrentLine) ;
}
splitted = content.toString().split("\\.");
} catch (IOException e) {
e.printStackTrace();
}
replace
splitted = sCurrentLine.split(".");
with
splitted = sCurrentLine.split("\\.");
EDIT
String sCurrentLine = null;
int i = 0;
br = new BufferedReader(new FileReader(rdfInstanceFile));
StringBuilder content = new StringBuilder();
while ((sCurrentLine = br.readLine()) != null) {
content.append(sCurrentLine);
}
splitted = content.toString().split("\\.");
It'll work.
I'm working on a homework assignment and have run into an odd "ArrayOutOfBoundsException" error - I know what the error means (essentially I'm trying to reference a location in an array that isn't there) but I'm not sure why it's throwing that error? I'm not sure what I'm missing, but obviously there must be some logic error somewhere that I'm not seeing.
PhoneDirectory.java
import java.util.HashMap;
import java.io.*;
class PhoneDirectory {
private HashMap<String, String> directoryMap;
File directory;
public PhoneDirectory() { //create file for phone-directory
directory = new File("phone-directory.txt");
directoryMap = new HashMap<String, String>();
try(BufferedReader buffer = new BufferedReader(new FileReader(directory))) {
String currentLine;
while((currentLine = buffer.readLine()) != null) { //set currentLine = buffer.readLine() and check if not null
String[] fileData = currentLine.split(","); //create array of values in text file - split by comma
directoryMap.put(fileData[0], fileData[1]); //add item to directoryMap
}
}
catch(IOException err) {
err.printStackTrace();
}
}
public PhoneDirectory(String phoneDirectoryFile) {
directory = new File(phoneDirectoryFile);
directoryMap = new HashMap<String, String>();
try(BufferedReader buffer = new BufferedReader(new FileReader(directory))) {
String currentLine;
while((currentLine = buffer.readLine()) != null) { //set currentLine = buffer.readLine() and check if not null
String[] fileData = currentLine.split(","); //create array of values in text file - split by comma
directoryMap.put(fileData[0], fileData[1]); //add item to directoryMap
}
}
catch(IOException err) {
err.printStackTrace();
}
}
public String Lookup(String personName) {
if(directoryMap.containsKey(personName))
return directoryMap.get(personName);
else
return "This person is not in the directory.";
}
public void AddOrChangeEntry(String name, String phoneNumber) {
//ASK IF "IF-ELSE" CHECK IS NECESSARY
if(directoryMap.containsKey(name))
directoryMap.put(name,phoneNumber); //if name is a key, update listing
else
directoryMap.put(name, phoneNumber); //otherwise - create new entry with name
}
public void DeleteEntry(String name) {
if(directoryMap.containsKey(name))
directoryMap.remove(name);
else
System.out.println("The person you are looking for is not in this directory.");
}
public void Write() {
try(BufferedWriter writeDestination = new BufferedWriter(new FileWriter(directory)))
{
for(String key : directoryMap.keySet())
{
writeDestination.write(key + ", " + directoryMap.get(key) + '\n');
writeDestination.newLine();
}
}
catch(IOException err) {
err.printStackTrace();
}
}
}
Driver.java
public class Driver {
PhoneDirectory list1;
public static void main(String[] args) {
PhoneDirectory list1 = new PhoneDirectory("test.txt");
list1.AddOrChangeEntry("Disney World","123-456-7890");
list1.Write();
}
}
Essentially I'm creating a file called "test.txt" and adding the line "Disney World, 123-456-7890" - what's weird is that the code still works - but it throws me that error anyway, so what's really happening? (For the record, I'm referring to the line(s): directoryMap.put(fileData[0], fileData[1]) - which would be line 14 and 28 respectively.)
I am trying to write to a text file. I am able to write to the console however, i am not able to write to my text file. One thing i have noticed is that String data doesn't contain any data if i were to just print to the console which is probably why nothing appears in my textfile. Does anyone know why that is though and how i can come about it?
writeFile() method code:
public static void writeFile(String filename, String content) throws IOException
{
try
{
Files.write(Paths.get(filename), content.getBytes()); // write file
}
catch (IOException e)
{
System.out.println("Error writing file: " + e);
}
}
Test code:
public class QuickTest {
public static void main(String... p) throws IOException {
List<SensorInfo> readings = new ArrayList<>();
SensorInfo info = null;
String data = createStringFromInfo(readings);
writeFile("datastore.txt", data);
String filedata = readFile("client-temp.txt");
List<SensorInfo> temps = createInfoFromData(filedata);
System.out.println(header());
for (SensorInfo reading : temps) {
System.out.print(reading.display());
}
}
}
CreateFromInfo Method:
public static String createStringFromInfo(List<SensorInfo> infoList)
{
String data = "";
for (SensorInfo info : infoList)
{
data += info.asData();
}
return data;
}
createInfoFromData
public static List<SensorInfo> createInfoFromData(String data)
{
List<SensorInfo> infoList = new ArrayList<>();
String[] lines = data.split("\n");
for (String line : lines)
{
SensorInfo info = new SensorInfo(line);
infoList.add(info);
}
return infoList;
}
That implementation of createStringFromInfo() confirms my guess: it will return an empty string when its argument is an empty list, as is the case in your program. I agree with you that that is why you get an empty file.
You fix it by filling the readings list with SensorInfo objects describing the information you want written to the file (before you invoke createStringFromInfo()). If the data for those SensorInfo objects should come from reading file "client-temp.txt" then you should read it in first, then pass that List to createStringFromInfo() to get the data to write.