How to add each value to a separate line? - java

My code does read and write the file, but it is not on a new line for every value and instead prints every value in one line.
// 2 points
static void Q1(String inputFilename, String outputFilename) {
// You are given a csv file (inputFilename) with all the data on a single line. Separate the
// values by commas and write each value on a separate line in a new file (outputFilename)
String data = "";
try {
for(String s :Files.readAllLines(Paths.get(inputFilename))){
data = data + s;
}
Files.write(Paths.get(outputFilename), data.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
As such the grader says:
Incorrect on input: [data/oneLine0.csv, output0.txt]
Expected output : overwrought plastic bomb
wrapped litter basket
obstetric matter of law
diabetic stretching
spatial marathi
continental prescott
reproductive john henry o'hara
hollow beta blocker
stereotyped national aeronautics and space administration
irremediable st. olaf
brunet fibrosis
embarrassed dwarf elm
superficial harrier
disparaging whetstone
consecrate agony
impacted lampoon
nefarious textile
some other organisation
Your output : overwrought plastic bomb,wrapped litter basket,obstetric matter of law,diabetic stretching,spatial marathi,continental prescott,reproductive john henry o'hara,hollow beta blocker,stereotyped national aeronautics and space administration,irremediable st. olaf,brunet fibrosis,embarrassed dwarf elm,superficial harrier,disparaging whetstone,consecrate agony,impacted lampoon,nefarious textile,some other organisation

String data = "";
try {
// input file has all data on one line, for loop isn't necessary here
// input file has elements separated by comma characters
for(String s : Files.readAllLines(Paths.get(inputFilename))){
data = data + s;
}
String[] separated = data.split(",");// does not handle embedded commas well
data = "";
// output file should have each comma separated value on its own line
for (String t : separated) {
data = data + t + System.getProperty("line.separator");
}
Files.write(Paths.get(outputFilename), data.getBytes());
}

First of all, you need to remove the comma from the CSV file. I'd suggest using
s = s.replace(",",""); Additionally, you must append a \n to each string to make it appear on a new line. So, you should add s += "\n"; This yields the code:
// 2 points
static void Q1(String inputFilename, String outputFilename) {
// You are given a csv file (inputFilename) with all the data on a single line. Separate the
// values by commas and write each value on a separate line in a new file (outputFilename)
String data = "";
try {
for(String s :Files.readAllLines(Paths.get(inputFilename))){
s.replace(",","");
s += "\n";
data = data + s;
}
Files.write(Paths.get(outputFilename), data.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}

Related

What is wrong in my file reading with Scanner class?

Every time I run it, gives this message (( InputMismatchException )) where is the problem from ?
File f = new File("nameList.txt");
try {
PrintWriter out;
out = new PrintWriter(f);
for (int i = 0; i < 4; i++) {
out.printf("Name : %s Age : %d ", "Rezaee-Hadi", 19);
out.println("");
}
out.close();
} catch (IOException ex) {
System.out.println("Exception thrown : " + ex);
}
try {
Scanner in = new Scanner(f);
String name = in.nextLine();
int age = in.nextInt();
for (int i = 0; i < 4; i++) {
System.out.println(name);
System.out.println(age);
}
in.close();
} catch (FileNotFoundException ex) {
System.out.println("Exception thrown : " + ex);
}
You are creating your data file in the following data format:
Name : Rezaee-Hadi Age : 19
Now, it really doesn't matter (to some extent) how you format your data file as long as you realize that you may need to parse that data later on. You really don't need to maintain a header with your data on each file line. We already know that the first piece of data on any file line is to be a Name and the second piece of data on any file line is to be the Age of the person the Name relates to. So, the following is sufficient:
Rezaee-Hadi, 19
If you want, you can place a header as the very first line of the data file so that it can easily be determined what each piece of data on each line relates to, for example:
Name, Age
Rezaee-Hadi, 19
Fred Flintstone, 32
Tom Jones, 66
John Smith, 54
This is actually a typical format for CSV data files.
Keeping with the file data format you are already using:
There is nothing wrong with using the Scanner#nextLine() method. It's a good way to go but you should be iterating through the file line by line using a while loop because you may not always know exactly how many actual data lines are contained within the file, for example:
Scanner in = new Scanner(f);
String dataLine;
while (in.hasNextLine()) {
dataLine = in.nextLine().trim();
// Skip Blank Lines
if (dataLine.equals("")) {
continue;
}
System.out.println(dataLine);
}
This will print all the data lines contained within your file. But this is not what you really want is it. You want to separate the name and age from each line which means then that you need to parse the data from each line. One way (in your case) would be something like this:
String dataLine;
Scanner in = new Scanner(f);
while (in.hasNextLine()) {
dataLine = in.nextLine().trim();
// Skip Blank Lines
if (dataLine.equals("")) {
continue;
}
String[] dataParts = dataLine.replace("Name : " , "").split(" Age : ");
System.out.println("The Person's Name: " + dataParts[0] + System.lineSeparator()
+ "The Person's Age: " + dataParts[1] + System.lineSeparator());
}
In the above code we iterate through the entire data file one line at a time using a while loop. As each line is read into the dataLine string variable it is also trimmed of any leading or trailing whitespaces. Normally we don't want these. We then check to make sure the line is not blank. We don't normally want these either and here we skip past those blank lines by issuing a continue to the while loop so as to immediately initiate another iteration. If the file line line actually contains data then it is held within the dataLine variable.
Now we want to parse that data so as to retrieve the Name and the Age and place them into a String Array. We do this by using the String#split() method but first we get rid of the "Name : " portion of the line using the String#replace() method since we don't want to deal with this text while we parse the line. In the String#split() method we supply a string delimiter to split by and that delimiter is " Age : ".
String[] dataParts = dataLine.replace("Name : " , "").split(" Age : ");
Now when each line is parsed, the Name and Age will be contained within the dataParts[] string array as elements located at index 0 and index 1. We now use these array elements to display the results to console window.
At this point the Age is a string located in the dataParts[] array at index 1 but you may want to convert this age to a Integer (int) type value. To do this you can utilize the Integer.parseInt() or Integer.valueOf() methods but before you do that you should validate the fact the the string you are about to pass to either of these methods is indeed a string numerical integer value. To do this you would utilize the String#matches() method along with a simple little Regular Expression (RegEx):
int age = 0;
if (dataParts[1].matches("\\d+")) {
age = Integer.parseInt(dataParts[1]);
// OR age = Integer.valueOf(dataParts[1]);
System.out.println("Age = " + age);
}
else {
System.out.println("Age is not a numerical value!");
}
The regular expression "\\d+" placed within the String#matches() method basically means, "Is the supplied string a string representation of a integer numerical value?". If the method finds that it is not then boolean false is returned. If it finds that the value supplied is a string integer numerical value then boolean true is returned. Doing things this way will prevent any NumberFormatException's from occurring.
Replace this:
int age=0;
while (in.hasNext()) {
// if the next is a Int,
// print found and the Int
if (in.hasNextInt()) {
age = in.nextInt();
System.out.println("Found Int value :"
+ age);
}
}
in place of this:
int age = in.nextInt();
Then you will not get "InputMismatchException" anymore..

Read CSV file and write to another CSV - ArrayIndexOutOfBoundsException and pattern difficuties

I'm creating a java program that reads data from one csv file and saves with little changes to another csv file:
a) In 3rd column of output file I must extract only price in specific format (e.g. 4.99, 2522.78) from 4th column in input file
b) In 4th colum of otput file I must extract date in formt DD.MM.YYYY from 5th column in input file if it is.
c) The input file in the last three rows hasn't got last column. It causes when I read lines and want read first row with no last column it throws me exception.
There is a litte more, but those are difficulties to overcome. Could you help me? I have pattern but I just don't know how to use it in table like mine.
Code:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RwCSV {
private static final String SOURCE_FILE = "/home/krystian/Pulpit/products.csv";
private static final String RESULT_FILE = "/home/krystian/Pulpit/result3.csv";
private static final String DELIMITER1 = ";";
private static final String DELIMITER2 = "|";
//Pattern pattern;
public static void main(String[] args) {
try (
BufferedReader br = new BufferedReader(new FileReader(SOURCE_FILE));
FileWriter fw = new FileWriter(RESULT_FILE)) {
String line;
while ((line = br.readLine()) != null) {
String[] values = line.split(DELIMITER1);
String[] result = new String[5];
Pattern p = Pattern.compile("\\d+.\\d\\d");
Matcher m = p.matcher(values[3]);
//System.out.println(values[4]);
result[0] = "'"+values[0]+"'";
result[1] = "'"+values[1]+"?id="+values[2]+"'";
result[2] = "'"+values[3]+"'";
result[3] = "'"+values[3]+"'";
result[4] = "'"+values[4]+"'"; //throws exception java.lang.ArrayIndexOutOfBoundsException
for (int i = 0; i < result.length; i++) {
fw.write(result[i].replace("\"", ""));
if (i != result.length - 1) {
fw.write(DELIMITER2);
}
if (values.length<5) {continue;}
}
fw.write("\n");
}
} catch (FileNotFoundException ex) {
System.out.println("File not found.");
} catch (IOException ex) {
ex.printStackTrace(System.out);
}
catch (NullPointerException ex) {
}
}
}
Input file:
"Product Name";"Link";"SKU";"Selling-Price";"description"
"Product #1";"http://mapofmetal.com";"AT-23";"USD 1,232.99";"This field contains no date!"
"Product #2";"http://mapofmetal.com";"BU-322";"USD 8654.56";"Here a date: 20.09.2014"
"Product #3";"http://mapofmetal.com";"FFZWE";"EUR 1255,59";"Another date: 31.4.1999"
"Product #4";"http://mapofmetal.com";234234;"345,99 €";"Again no date in this field."
"Product #5";"http://mapofmetal.com";"UDMD-4";"$34.00";"Here are some special characters: öäüß"
"Product #6";"http://mapofmetal.com";"33-AAU43";"431.333,0 EUR";"American date: 12-23-2003"
"Product #7";"http://mapofmetal.com";"33-AAU44";"431.333,0 EUR";"One more date: 1.10.2014"
"Product #8";"http://mapofmetal.com";"33-AAU45";"34,99";
"Product #9";"http://mapofmetal.com";"UZ733-2";234.99;
"Product #10";"http://mapofmetal.com";"42-H2G2";42;
Output file row pattern (must be changed separator and quote-character):
'Product #2'|'http://mapofmetal.com?id=BU-322'|'8654.56'|'20.09.2014'
About the ArrayIndexOutOfBounds
Your problem seems to be that when the input ends with ;, the 5th element gets discarded. For example:
"abc;def;".split(";") -> ["abc", "def"]
Instead of what you would like, ["abc", "def", ""]
To have that effect, either pass the number elements you expect as a second parameter to .split(), for example:
"abc;def;".split(";", 3) -> ["abc", "def", ""]
Or a negative value:
"abc;def;".split(";", -1) -> ["abc", "def", ""]
This is explained in the docs.
About extracting the price
Extracting the price is tricky because you have multiple formats:
USD 1,232.99
EUR 1255,59
345,99 €
$34.00
34,99
The biggest problem there is the comma, which sometimes should be ignored, other times it's a decimal point.
Here's something that will work with the example you gave, but is likely not exhaustive, and you would need to improve on it depending on the other possible inputs you might have:
String price;
if (values[3].startsWith("EUR ") || values[3].endsWith(" €")) {
// ignore non-digits and non-commas, and replace commas with dots
price = values[3].replaceAll("[^\\d,]", "").replaceAll(",", ".");
} else {
// ignore non-digits and non-dots
price = values[3].replaceAll("[^\\d.]", "");
}
Then there's this format I'm not sure what to make of:
431.333,0 EUR
I think you need better specs for the input format.
It's unnecessarily hard and error-prone to work with such inconsistent input.
Depending on how long you want to use this code there are quick vs. More robust options.
An easy one is to add a try and catch around checking for a result in values [4] and then insert a default value in the catch when not present in the file.
Your products file only has 4 columns starting a "Product #8". So you are trying to access values[4] and there that array index doesn't exist.

Reading a records file and create a index for it

So I need to read from a records file where '#' determines the end of a record and '|' the end of a field like this: #9783642217074|Interaction|Macie|Furtado,Elizabeth|Winckler,Marco|2011#.
Then I need to write just the first field of each record in another file.
I'm trying to use Java I/O RandomAccessFile but I really need some light to figure it out.
If anyone could tell what methods or the ideia behind this Ill be thankful.
You do not need RandomAccessFile, you would be fine with reading and writing your files character-by-character.
Your program can be in any of these three states:
Waiting for the start of the next record
Writing the content of the first field
Waiting for the end of the record
The program changes its state as follows:
Initially, it is in the state number 1
When # character is detected in state 1, the state becomes 2
When | is detected in state 2, the state becomes 3
When # is detected in state 3, the state becomes 1.
Each character received in state 2 is duplicated into the output file
When the state transitions from 3 to 1, write a separator into the output.
This should be really straightforward to code with a single loop that reads from a file, and a handful of if-then-else statements. Make a variable called state outside the loop, set it to 1, open the input and the output files, and make a loop to read the input character-by-character until the end of the file is reached.
Here is an implementation using the Scanner class.
Main.class
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// The path of the project
String basePath = new File("").getAbsolutePath();
// The path of the record file, in relevance to <basePath>
String recordPath = basePath.concat("/RecordList.txt");
// Make sure that path is correct
System.out.println(recordPath + "\n");
// Store all Record objects in an array
ArrayList<Record> recordArray = new ArrayList<Record>();
// Lets try to read the file, and parse each line at a time
try {
// input the file content to the String "input"
BufferedReader file = new BufferedReader(new FileReader(recordPath));
// Store every line of <file> in <input> String
String line;
String input = "";
while ((line = file.readLine()) != null) {
input += line + '\n';
// Remove the # symbols at beginning and end
line = line.replaceFirst("#", "");
System.out.println(line);
//
String recordData[] = line.split("[|]");
Record record = new Record(recordData);
recordArray.add(record);
}
// Make sure to close the <file>
file.close();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println();
//Verify results
for (Record record : recordArray) {
System.out.println(record.toString());
}
}
}
Record.class
public class Record {
// #9783642217074|Interaction|Macie|Furtado,Elizabeth|Winckler,Marco|2011#
private String id;
private String field2;
private String field3;
private String field4;
private String field5;
private String year;
public Record(String[] recordData) {
this.id = recordData[0];
this.field2 = recordData[1];
this.field3 = recordData[2];
this.field4 = recordData[3];
this.field5 = recordData[4];
this.year = recordData[5];
}
/* (non-Javadoc)
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
return "Record [id=" + id + ", field2=" + field2 + ", field3="
+ field3 + ", field4=" + field4 + ", field5=" + field5
+ ", year=" + year + "]";
}
}
And here is the RecordFile.txt I generated (mind the data I made up)
#9783642217074|Interaction|Macie|Furtado,Elizabeth|Winckler,Marco|2011#
#9783612343243|Interaction|Freddie|Fuder,Franscon|Winner,Marie|2013#
#9213432423534|Interaction|Jimbo|Furtado,Melo|Yakasabi,Johnson|2001#
As always, please use my code as a reference. It is always better to learn how to write code yourself, especially when this question pertains to a homework assignment.

Cannot get values from splitted Array String into a String

I am trying to get the values out of String[] value; into String lastName;, but I get errors and it says java.lang.ArrayIndexOutOfBoundsException: 2
at arduinojava.OpenFile.openCsv(OpenFile.java:51) (lastName = value[2];). Here is my code, but I am not sure if it is going wrong at the split() or declaring the variables or getting the data into another variable.
Also I am calling input.next(); three times for ignoring first row, because otherwise of study of Field of study would also be printed out..
The rows I am trying to share are in a .csv file:
University Firstname Lastname Field of study
Karlsruhe Jerone L Software Engineering
Amsterdam Shahin S Software Engineering
Mannheim Saman K Artificial Intelligence
Furtwangen Omid K Technical Computing
Esslingen Cherelle P Technical Computing
Here's my code:
// Declare Variable
JFileChooser fileChooser = new JFileChooser();
StringBuilder sb = new StringBuilder();
// StringBuilder data = new StringBuilder();
String data = "";
int rowCounter = 0;
String delimiter = ";";
String[] value;
String lastName = "";
/**
* Opencsv csv (comma-seperated values) reader
*/
public void openCsv() throws Exception {
if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
// Get file
File file = fileChooser.getSelectedFile();
// Create a scanner for the file
Scanner input = new Scanner(file);
// Ignore first row
input.next();
input.next();
input.next();
// Read from input
while (input.hasNext()) {
// Gets whole row
// data.append(rowCounter + " " + input.nextLine() + "\n");
data = input.nextLine();
// Split row data
value = data.split(String.valueOf(delimiter));
lastName = value[2];
rowCounter++;
System.out.println(rowCounter + " " + data + "Lastname: " + lastName);
}
input.close();
} else {
sb.append("No file was selected");
}
}
lines are separated by spaces not by semicolon as per your sample. Try in this way to split based on one or more spaces.
data.split("\\s+");
Change the delimiter as shown below:
String delimiter = "\\s+";
EDIT
The CSV file should be in this format. All the values should be enclosed inside double quotes and there should be a valid separator like comma,space,semicolon etc.
"University" "Firstname" "Lastname" "Field of study"
"Karlsruhe" "Jerone" "L" "Software Engineering"
"Amsterdam" "Shahin" "S" "Software Engineering"
Please check if you file is using delimiter as ';' if not add it and try it again, it should work!!
Use OpenCSV Library for read CSV files .Here is a detailed example on read/write CSV files using java by Viral Patel

How do sort my pattern match results as complete match, half a match and so on [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Regular expression not matching subwords in phrase
My program displays the matching results, but I want to sort the results as complete match (100%), half a match and so on.
My text file contains the following line:
Red car
Red
Car
So If I search for: “red car”. I get the following results
Red car
Red
Car
So what I want to do is to sort the found results as follows:
"red car" 100% match
"red" 40% match
"car" 40% match
Any help is appreciated.
Any help is appreciated. My code is as follows:
public static void main(String[] args) {
// TODO code application logic here
String strLine;
try{
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream("C:\\textfile.txt"");
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
Scanner input = new Scanner (System.in);
System.out.print("Enter Your Search: "); // String key="red or yellow";
String key = input.nextLine();
while ((strLine = br.readLine()) != null) {
Pattern p = Pattern.compile(key); // regex pattern to search for
Matcher m = p.matcher(strLine); // src of text to search
boolean b = false;
while(b = m.find()) {
System.out.println( " " + m.group()); // returns index and match
// Print the content on the console
}
}
//Close the input stream
in.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
Assuming you are searching for "Red" or "Yellow", and or is the only logical operator you need (no 'and' or 'xor') and you don't want to use any wildcards or regular-expressions in what you search for, then I would simply loop through, trying to match each String in turn against the line. In pseudo-code, something like:
foreach (thisLine: allLinesInTheFile) {
numOfCharsMatching = 0
foreach (thisString: allSearchStrings) {
if (thisLine.contains(thisString) {
numOfCharsMatching = numOfCharsMatching + thisString.length
}
}
score = ( numOfCharsMatching / thisLine.length ) * 100
}
If you don't want spaces to count in your score, then you'd need to remove them from the thisString.length (and not allow them in your search terms)
One other problem is the numOfCharsMatching will be incorrect if matches can overlap (i.e. if searching for 'row' or 'brown' in 'brown row' it will say that there are 11 characters matching, longer than the length of the string. You could use a BitSet to track which characters have been involved in a match, something like:
foreach (thisLine: allLinesInTheFile) {
whichCharsMatch = new BitSet()
foreach (thisString: allSearchStrings) {
if (thisLine.contains(thisString) {
whichCharsMatch.set(startPositionOfMatch, endPositionOfMatch, true)
}
}
score = ( numOfCharsMatching / thisLine.length ) * 100
}
Have a look at the BitSet javadoc, particularly the set and cardinality methods

Categories