Reading a .csv file (The system cannot find the file specified) - java

I see this question and similar questions already but my problem is that it was working fine until a moment ago. Where did I go wrong?
This is a small example I made to work out how to read a .csv file and to pass the values in it to something else, before implementing it in a larger application.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
String fileName = "data.csv";
File file = new File(fileName);
try {
Scanner inputStream = new Scanner(file);
inputStream.next();//Ignore first line
while(inputStream.hasNext()) {
String data = inputStream.next();//gets a whole line
//create a string array where value at 0 is the name, value at 1 is the quantity, and value at 2 is the price
String[] values = data.split(",");
int quantity = Integer.parseInt(values[1]);
System.out.println(values[0] + "\n" + quantity + "\n" + values[2]);
}
inputStream.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}}
I went to do this for my larger program and it gave me the page not found error and when I went to double check this project, it would not run either. It gives me the same error. I restarted Eclipse and checked a few times to find if I accidentally left something out or changed something. data.csv is right there in my src folder. I even dagged it over to make it show up in the Eclipse project view. What am I missing?
Name,Quantity,Price
Tea,100,2.50
Coke,50,2.50
Lays,32,1.00
Cheetos,34,1.10
Snickers,30,1.25
Butterfinger,70,1.50
Five,40,0.75
Orbits,50,0.90

This is limited to the easiest, most powerful way of using opencsv to allow you to hit the ground running.
For reading, create a bean to harbor the information you want to read, annotate the bean fields with the opencsv annotations, then do this:
List<MyBean> beans = new CsvToBeanBuilder(FileReader("yourfile.csv"))
.withType(Visitors.class).build().parse();
For writing, create a bean to harbor the information you want to write, annotate the bean fields with the opencsv annotations, then do this:
// List<MyBean> beans comes from somewhere earlier in your code.
Writer writer = new FileWriter("yourfile.csv");
StatefulBeanToCsvBuilder beanToCsv = StatefulBeanToCsvBuilder(writer).build();
beanToCsv.write(beans);
writer.close();
Say you're using a tab for your separator, you can do something like this:
CSVReader reader = new CSVReader(new FileReader("yourfile.csv"), '\t');
or for reading with annotations:
CsvToBean csvToBean = CsvToBeanBuilder(new FileReader("yourfile.csv"))
.withSeparator('\t').build();
And if you single-quoted your escaped characters rather than double-quoting them, you can use the three-argument constructor:
CSVReader reader = new CSVReader(new FileReader("yourfile.csv"), '\t', '\'');
or for reading with annotations:
CsvToBean csvToBean = CsvToBeanBuilder(new FileReader("yourfile.csv"))
.withSeparator('\t').withQuoteChar('\'').build();
At the most basic, you can use opencsv to parse an input and return a String[], thus:
CSVReader reader = new CSVReader(new FileReader("yourfile.csv"));
String [] nextLine;
while ((nextLine = reader.readNext()) != null) {
// nextLine[] is an array of values from the line
System.out.println(nextLine[0] + nextLine[1] + "etc...");
}

Well I'm not sure why "data.csv" stopped working but, I changed the path to "src/data.csv" and it works fine. Which begs the question, why did it work one moment and not the next?

Related

CsvMalformedLineException: Unterminated quoted field at end of CSV line

I am writing code to process a list of tar.gz files, inside which there are multiple, csv files. I have encountered the error below
com.opencsv.exceptions.CsvMalformedLineException: Unterminated quoted field at end of CSV line. Beginning of lost text: [,,,,,,
]
at com.opencsv.CSVReader.primeNextRecord(CSVReader.java:245)
at com.opencsv.CSVReader.flexibleRead(CSVReader.java:598)
at com.opencsv.CSVReader.readNext(CSVReader.java:204)
at uk.ac.shef.inf.analysis.Test.readAllLines(Test.java:64)
at uk.ac.shef.inf.analysis.Test.main(Test.java:42)
And the code causing this problem is below, on line B.
public class Test {
public static void main(String[] args) {
try {
Path source = Paths.get("/home/xxxx/Work/data/amazon/labelled/small/Books_5.json.1.tar.gz");
InputStream fi = Files.newInputStream(source);
BufferedInputStream bi = new BufferedInputStream(fi);
GzipCompressorInputStream gzi = new GzipCompressorInputStream(bi);
TarArchiveInputStream ti = new TarArchiveInputStream(gzi);
CSVParser parser = new CSVParserBuilder().withStrictQuotes(true)
.withQuoteChar('"').withSeparator(',').
.withEscapeChar('|'). // Line A
build();
BufferedReader br = null;
ArchiveEntry entry;
entry = ti.getNextEntry();
while (entry != null) {
br = new BufferedReader(new InputStreamReader(ti)); // Read directly from tarInput
System.out.format("\n%s\t\t > %s", new Date(), entry.getName());
try{
CSVReader reader = new CSVReaderBuilder(br).withCSVParser(parser)
.build();
List<String[]> r = readAllLines(reader);
} catch (Exception ioe){
ioe.printStackTrace();
}
System.out.println(entry.getName());
entry=ti.getNextEntry(); // Line B
}
}catch (Exception e){
e.printStackTrace();
}
}
private static List<String[]> readAllLines(CSVReader reader) {
List<String[]> out = new ArrayList<>();
int line=0;
try{
String[] lineInArray = reader.readNext();
while(lineInArray!=null) {
//System.out.println(Arrays.asList(lineInArray));
out.add(lineInArray);
line++;
lineInArray=reader.readNext();
}
}catch (Exception e){
System.out.println(line);
e.printStackTrace();
}
System.out.println(out.size());
return out;
}
}
I also attach a screenshot of the actual line within the csv file that caused this problem here, look at line 5213. I also include a test tar.gz file here: https://drive.google.com/file/d/1qHfWiJItnE19-BFdbQ3s3Gek__VkoUqk/view?usp=sharing
While debugging, I have some questions.
I think the issue is the \ character in the data file (line 5213 above), which is the escape character in Java. I verified this idea by adding line A to my code above, and it works. However, obviously I don't want to hardcode this as there can be other characters in the data causing same issue. So my question 1 is: is there anyway to tell Java to ignore escape characters? Something like the opposite of withEscapeChar('|')? UPDATE: the answer is to use '\0', thanks to the first comment below.
When debugging, I notice that my program stops working on the next .csv file within the tar.gz file as soon as it hit the above exception. To explain what I mean, inside the tar.gz file included in the above link, there are two csvs: _10.csv and _110.csv. The problematic line is in _10.csv. When my program hit that line, an exception is thrown and the program moves on to the next file _110.csv (entry=ti.getNextEntry();). This file is actually fine, but the method readAllLines that is supposed to read this next csv file will throw the same exception immediately on the first line. I don't think my code is correct, especially the while loop: I suspect the input stream was still stuck at the previous position that caused the exception. But I don't know how to fix this. Help please?
using RFC4180Parser worked for me.

How to take a specific line from a text file and read it into an array? (Java)

I've been trying to code a quiz game in javafx where I store the questions on a text file and then randomize a number then use it to call the line of the same number on the text file and read it into an array.
After looking online I can only seem to find how to read a text file line by line instead of a specific line. I also use the following code to read the text file but am unsure where to go on from there.
File file = new File("/Users/administrator/Desktop/Short Questions.txt");
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line;
This may help you
You need to change file path as per your file location
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new FileReader("C:\\Users\\everestek22\\Desktop\\Invoice.txt"));
String[] strArray =
bufferedReader.lines().map(String::new).toArray(String[]::new);
// String line = bufferedReader.readLine();
// while (line != null) {
// System.out.println(line);
// line = bufferedReader.readLine();
// String[] strArray = bufferedReader.lines().map(String::new).toArray(String[]::new);
// }
bufferedReader.close();
for (String s : strArray) {
System.out.println(s);
}
}
}
Don't bother trying to read specific lines from the file, just read all the lines from the file, then lookup your question by index in the resultant list.
List<String> questions = Files.readAllLines(
Paths.get("<your file path>")
);
Then you could choose a question at random:
Random random = new Random(42);
int randomQuestionIndex = random.nextInt(questions.size());
String randomQuestion = questions.get(randomQuestionIndex);
Using 42 as the seed to the random number generator makes the random sequence repeatable, which is good for testing. To have it truly psuedo-random, then remove the seed (e.g. just new Random());
If the structure of the data you wish to read is complex, then use a helper library such as Jackson to store and retrieve the data as serialized JSON objects. If it is even more complex, then a database can be used.
If you have a really large file and you know the position in the file of each specific thing you wish to read, then you can use a random access file for lookup. For example, if the all the questions in the file are exactly the same length and you know how many questions are stored there, then a random access file might be used fairly easily. But, from your description of what you need to do, this is likely not the case, and the simpler solution of reading everything rather than using a random access file is better.

Create a new CSV file with java to add a new column

I am looking at the performance of a particular stock over a period of 30 days. I downloaded the data from Yahoo finance which appears as a CSV file. If I would like to create a new column in my dataset to show the daily percentage change between open and close using java refer to column H as where the output should appear, how should I do so?
Thanks in advance!
You can just edit your file line-by-line and add a separator character using the concat() function.
Open the file with a FileReader or BufferedReader and then start parsing.
Official Javadoc: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#concat(java.lang.String)
Please see also this.
With OpenCSV: http://opencsv.sourceforge.net/
public class OpenCSVTest {
public static void main(String[] args) {
StringWriter target = new StringWriter();
try(CSVReader reader = new CSVReader(new StringReader("my,test"));
CSVWriter writer = new CSVWriter(target);) {
for(String[] line : reader) {
String[] added = Arrays.copyOf(line, line.length + 1);
added[added.length-1] = "addition";
writer.writeNext(added);
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(target.toString());
}
}
You can replace the StringReader and StringWriter with your input and output. The reader will then iterate through each line in your csv for you. You can make a copy of the original line and add your new column and write it out into the target.
Breakdown of the code:
try(CSVReader reader = new CSVReader(new StringReader("my,test"));
CSVWriter writer = new CSVWriter(target);) { ... }
This is a try-with-resources block. It makes sure that the reader and writer are closed after they are done.
for(String[] line : reader) {
String[] added = Arrays.copyOf(line, line.length + 1);
added[added.length-1] = "addition";
writer.writeNext(added);
}
This is a standard for loop. The CSVReader implements the Iterable interface, which enables us to use it in the for loop directly.
Arrays.copyOf(line, line.length + 1); is a function that creates a copy of the array passed to it, but with a new size. Because you want to add a column, we make a copy of the original array my,test and add 1 more space at the end of it, where we can then assign the new value to it by doing: added[added.length-1] = "addition";
Finally, we just pass that to the writer which will then correctly write the values into the target, in this case a StringWriter, in your case likely a file.

reading in csv file and storing in arrays

the practice question i got says that i need to
create a java code that reads in csv file with name and height.
to read a file you must get a file name from user as string.
then you must store contents of file into two arrays one for name (string) and height(real number).
You should read the file at least twice, once to check how many students are in the file (so you know how many students you need to store) and a couple more times to actually read the file (to get the names and height).
then prompt the user for name you want height of. it should output the height for userinput.
example csv file is
chris,180
jess,161
james, 174
its not much but this is all i could come up with i have no idea how to store name and height separately and use that array to output the results. and would i need to use split somewhere in the code? i remember learning it but dont know if its used in this situation
import.java.util.*;
private class StudentNameHeight
private void main (string [] args)
{
String filename;
Scanner sc = new scanner(system.in);
System.out.println("enter file name")
filename = sc.nextline();
readFile (filename);
}
private void readFile (String filename)
{
FileInputStream fileStrm = null;
InputStreamReader rdr;
BufferedReader bufRdr;
try
{
fileStrm = new FileInputStream(filename);
rdr = new InputStreamReader(fileStrm);
bufRdr = new BufferedReader(rdr);
// ?
catch (IOException e)
{
if (fileStrm != null)
{
try {fileStrm.close(); } catch (IOException e2){}
}
System.out.println("error in processing" + e.getMessage());
}
}
im new to java so, any small tip or help would be great
thanks
You code looks messy. As far as I understand from your question, you are willing to read a CSV file containing two entities, one is name and another is height and store these two entities in two different data structures. I'm teaching you a simple way to accomplish this in below code snippet.
public void processCSVFile(String filePath){
try(BufferedReader fileReader = new BufferedReader(new FileReader(new File(filePath)))){
//Create two lists to hold name and height.
List<String> nameList = new ArrayList<>();
List<Integer> heightList = new ArrayList<>();
String eachLine = "";
/*
* Read until you hit end of file.
*/
while((eachLine = fileReader.readLine()) != null){
/*
* As it is CSV file, split each line at ","
*/
String[] nameAndHeightPair = eachLine.split(",");
/*
* Add each item into respective lists.
*/
nameList.add(nameAndHeightPair[0]);
heightList.add(Integer.parseInt(nameAndHeightPair[1]));
}
/*
* If you are very specific, you can convert these
* ArrayList to arrays here.
*/
}catch(IOException e1){
e1.printStackTrace();
}
}

Java -- Need help to enhance the code

I wrote a simple program to read the content from text/log file to html with conditional formatting.
Below is my code.
import java.io.*;
import java.util.*;
class TextToHtmlConversion {
public void readFile(String[] args) {
for (String textfile : args) {
try{
//command line parameter
BufferedReader br = new BufferedReader(new FileReader(textfile));
String strLine;
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
Date d = new Date();
String dateWithoutTime = d.toString().substring(0, 10);
String outputfile = new String("Test Report"+dateWithoutTime+".html");
FileWriter filestream = new FileWriter(outputfile,true);
BufferedWriter out = new BufferedWriter(filestream);
out.write("<html>");
out.write("<body>");
out.write("<table width='500'>");
out.write("<tr>");
out.write("<td width='50%'>");
if(strLine.startsWith(" CustomerName is ")){
//System.out.println("value of String split Client is :"+strLine.substring(16));
out.write(strLine.substring(16));
}
out.write("</td>");
out.write("<td width='50%'>");
if(strLine.startsWith(" Logged in users are ")){
if(!strLine.substring(21).isEmpty()){
out.write("<textarea name='myTextBox' cols='5' rows='1' style='background-color:Red'>");
out.write("</textarea>");
}else{
System.out.println("else if block:");
out.write("<textarea name='myTextBox' cols='5' rows='1' style='background-color:Green'>");
out.write("</textarea>");
} //closing else block
//out.write("<br>");
out.write("</td>");
}
out.write("</td>");
out.write("</tr>");
out.write("</table>");
out.write("</body>");
out.write("</html>");
out.close();
}
//Close the input stream
in.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
}
public static void main(String args[]) {
TextToHtmlConversion myReader = new TextToHtmlConversion();
String fileArray[] = {"D:/JavaTesting/test.log"};
myReader.readFile(fileArray);
}
}
I was thinking to enhance my program and the confusion is of either i should use Maps or properties file to store search string. I was looking out for a approach to avoid using substring method (using index of a line). Any suggestions are truly appreciated.
From top to bottom:
Don't use wildcard imports.
Don't use the default package
restructure your readFile method in more smaller methods
Use the new Java 7 file API to read files
Try to use a try-block with a resource (your file)
I wouldn't write continuously to a file, write it in the end
Don't catch general Exception
Use a final block to close resources (or the try block mentioned before)
And in general: Don't create HTML by appending strings, this is a bad pattern for its own. But well, it seems that what you want to do.
Edit
Oh one more: Your text file contains some data right? If your data represents some entities (or objects) it would be good to create a POJO for this. I think your text file contains users (right?). Then create a class called Users and parse the text file to get a list of all users in it. Something like:
List<User> users = User.parse("your-file.txt");
Afterwards you have a nice user object and all your ugly parsing is in one central point.

Categories

Resources