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

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.

Related

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

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?

Program terminates while trying to sort doubles

I'm trying to create a method where it reads doubles from my .txt file which looks like:
Homer Simpson, 50.0
Zoidberg, 100
Peter Griffin, 34.0
Lisa Simpson, 100
and sort them in descending order, here's my code:
public static void sortGrade() throws IOException {
FileReader reader = new FileReader("Grades.txt");
BufferedReader buffer = new BufferedReader(reader);
Scanner input = new Scanner ("Grades.txt");
Double dGrade=0.0;
ArrayList<Double> grade = new ArrayList<Double>();
while (input.hasNextDouble())
{
grade.add(dGrade);
}
reader.close();
Collections.sort(grade, Collections.reverseOrder());
FileWriter fileWriter = new FileWriter("Grades.txt");
PrintWriter out = new PrintWriter(fileWriter);
for (Double outputLine : grade)
{
out.println(outputLine);
}
out.close();
}
}
After I call the method, it deletes my .txt file and terminates the program. Does anyone know what i'm doing wrong syntactically or logically?
You have several problems in your code:
You declare BufferedReader buffer = new BufferedReader(reader); but never use the buffer to read the data, instead you use the Scanner input.
Scanner input = new Scanner ("Grades.txt"); uses Scanner(String) which means it will use the String parameter as the source to read the data. You should pass it as a File instead, like this:
Scanner input = new Scanner(new File("Grades.txt"));
You're creating an output file with the same name and path of the input file, noted here:
FileWriter fileWriter = new FileWriter("Grades.txt");
Use a different name and location for this file, like:
FileWriter fileWriter = new FileWriter("Grades-out.txt");
In case you want/need to append data to the end of the output, then use FileWriter(String, boolean) and pass the second parameter as true.
FileWriter fileWriter = new FileWriter("Grades-out.txt");
Be aware that when you use this approach you have to manually clear the file before executing the application, otherwise you may have duplicated data in your input.
From 2, since you haven't read any double from "Gradex.txt" string, then there's no output in the file, so the current output file, Grades.txt, will be an empty file.
I recommend you to create a class called Person where you store both the name string and the double (whatever it means), then store every instance of Person in a List<Person> (backed by an ArrayList<Person>) and sort this list using a custom Comparator<Person> or by implementing Comparable<Person> in Person class.
You can use something like this (I always use a charset for reading, if you don't need it just don't use it):
List<Double> result = new LinkedList<>();
try (Scanner scanner = new Scanner(Paths.get("Grades.txt"), StandardCharsets.UTF_8.name())) {
while (scanner.hasNextLine()) {
result.add(Double.valueOf(scanner.nextLine().split(",")[1]));
}
} catch (IOException e) {
System.err.printf("Something happened here...this is why: %s", e);
}
Collections.sort(result, Collections.reverseOrder());
// Do your other stuff from now on...

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.

How to overcome out of memory exception with PrintWriter?

The following code reads a bunch of .csv files and then combines them into one .csv file. I tried to system.out.println ... all datapoints are correct, however when i try to use the PrintWriter I get:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space.
I tried to use FileWriter but got the same error. How should I correct my code?
public class CombineCsv {
public static void main(String[] args) throws IOException {
PrintWriter output = new PrintWriter("C:\\User\\result.csv");
final File file = new File("C:\\Users\\is");
int i = 0;
for (final File child: file.listFiles()) {
BufferedReader CSVFile = new BufferedReader( new FileReader( "C:\\Users\\is\\"+child.getName()));
String dataRow = CSVFile.readLine();
while (dataRow != null) {
String[] dataArray = dataRow.split(",");
for (String item:dataArray) {
System.out.println(item + "\t");
output.append(item+","+child.getName().replaceAll(".csv", "")+",");
i++;
}
dataRow = CSVFile.readLine(); // Read next line of data.
} // Close the file once all data has been read.
CSVFile.close();
}
output.close();
System.out.println(i);
}
}
I can only think of two scenarios in which that code could result in an OOME:
If the file directory has a very large number of elements, then file.listFiles() could create a very large array of File objects.
If one of the input files includes a line that is very long, then CSVFile.readLine() could use a lot of memory in the process of reading it. (Up to 6 times the number of bytes in the line.)
The simplest approach to solving both of these issues is to increase the Java heap size using the -Xmx JVM option.
I can see no reason why your use of a PrintWriter would be the cause of the problem.
Try
boolean autoFlush = true;
PrintWriter output = new PrintWriter(myFileName, autoFlush);
It creates a PrintWriter instance which flushes content everytime when there is a new line or format.

writing to text file using BufferedReader

my problem is to read non primes from txt file and write prime factors in same file.
i actually dont know how BufferedReader works.from my understanding i am trying to read the file data to buffer(8kb) and write prime factors to file.(by creating a new one)
class PS_Task2
{
public static void main(String[] args)
{
String line=null;
int x;
try
{
FileReader file2 = new FileReader("nonprimes.txt");
BufferedReader buff2=new BufferedReader(file2);
File file1 = new File("nonprimes.txt");
file1.createNewFile();
PrintWriter d=new PrintWriter(file1);
while((line = buff2.readLine()) != null)
{
x=Integer.parseInt(line);
d.printf ("%d--> ", x);
while(x%2==0)
{
d.flush();
d.print("2"+"*");
x=x/2;
}
for (int i = 3; i <= Math.sqrt(x); i = i+2)
{
while (x%i == 0)
{
d.flush();
d.printf("%d*", i);
x = x/i;
}
}
if (x > 2)
{
d.flush();
d.printf ("%d ", x);
}
d.flush();//FLUSING THE STREAM TO FILE
d.println("\n");
}
d.close(); // CLOSING FILE
}
feel free to give detailed explanation. :D thanks ~anirudh
reading and writing to a file in java doesnt EDIT the file, but clear the old one and creates a new one, you can use many approachesfor example, to get your data, modify it, and either save it on memory in a StringBuilder or a collection or what ever and re-write it again
well i created fileOne.txt containing the following data :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
and i want to multiply all those numbers by 10, then re-write them again :
public static void main(String [] args) throws Exception{ // just for the example
// locate the file
File fileOne = new File("fileOne.txt");
FileReader inputStream = new FileReader(fileOne);
BufferedReader reader = new BufferedReader(inputStream);
// create a LinkedList to hold the data read
List<Integer> numbers = new LinkedList<Integer>();
// prepare variables to refer to the temporary objects
String line = null;
int number = 0;
// start reading
do{
// read each line
line = reader.readLine();
// check if the read data is not null, so not to use null values
if(line != null){
number = Integer.parseInt(line);
numbers.add(number*10);
}
}while(line != null);
// free resources
reader.close();
// check the new numbers before writing to file
System.out.println("NEW NUMBERS IN MEMORY : "+numbers);
// assign a printer
PrintWriter writer = new PrintWriter(fileOne);
// write down data
for(int newNumber : numbers){
writer.println(newNumber);
}
// free resources
writer.flush();
writer.close();
}
this approach is not very good when dealing with massive data
As per your problem statement, you need to take input from a file, do some processing and write back the processed data in the same file. For this, please note the below points:
You may not create a file with same name in a directory, so you must create the new file at some other location; or write the content into different file and later rename it after deleting original one.
While your file is open for reading, modifying the same file is not a good idea. you could use below approach:
Read the content of the file and store in a data structure liek Arrays, ArrayList.
Close the file.
Process the data stored in the data structure.
Open the file in write mode (over-write mode rather than append mode)
Write back the processed data into the file.

Categories

Resources