I cannot write to my .CSV file - java

My guess is, the code I've written doesn't work with .CSV files, but only .txt.
The purpose of my code is to take the user input from field1, and check against my .CSV file to see if there is an instance of the user input located within the file. If there is, then it will be replaced by the user input from field2.
This works with my .txt file, but not with my .CSV file.
Here's the code that is activated at the push of a button (save button):
try{
// Input the file location into Path variable 'p'
//Cannot write to CSV files
//Path p = Paths.get("C:\\Users\\myname\\Documents\\Stock Take Program\\tiger.csv");
Path p = Paths.get("C:\\Users\\myname\\Desktop\\test.txt");
//Read the whole file to a ArrayList
List<String> fileContent = new ArrayList<>(Files.readAllLines(p));
//Converting user input from editSerialField to a string
String strSerial = editSerialField.getText();
//Converting user input from editLocationField to a string
String strLocation = editLocationField.getText();
//This structure looks for a duplicate in the text file, if so, replaces it with the user input from editLocationField.
for (int i = 0; i < fileContent.size(); i++)
{
if (fileContent.get(i).equals(strSerial))
{
fileContent.set(i, strLocation);
}
break;
}
// write the new String with the replaced line OVER the same file
Files.write(p, fileContent);
}catch(IOException e)
{
e.printStackTrace();
}
My question is, how can I update my code to work with updating and replacing the contents of a .CSV file with the user input, the same way as it works for my .txt files.
When writing to a text file, it replaces only the first line, but when writing to a .CSV file, it does not replace anything.
Is there anyway I should be writing my code differently to replace text within a .CSV file.
Any help is greatly appreciated, thanks.

I'm an idiot. My '.CSV' file is actually titled tiger.csv as a text file. I've now saved an actual CSV version and it is now working.
Haha, thanks for the help guys.

Probably should be in another question, but the problem relating to the change only working on the first line is due to the break being called and shortcutting the loop on the first way round. Put it within the if block.
for (int i = 0; i < fileContent.size(); i++)
{
if (fileContent.get(i).equals(strSerial))
{
fileContent.set(i, strLocation);
break;
}
}
Or leave it off completely if you want it to be able to update multiple lines.

HTH,
public static void main(String[] args) throws FileNotFoundException {
String UserEntredValu="Karnataka";
String csvFile = "C:/Users/GOOGLE/Desktop/sample/temp.csv";
String line = "";
String cvsSplitBy = ",";
PrintWriter pw = null;
pw = new PrintWriter(new File(csvFile));
try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {
while ((line = br.readLine()) != null) {
// use comma as separator
String[] country = line.split(cvsSplitBy);
for( int i = 0; i < country.length - 1; i++)
{
String element = country[i];
if(element.contains(UserEntredValu)){
String newEle=element.replace(element, "NEW INDIA");
pw.write(newEle);
System.out.println("done!");
pw.close();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}

Related

Using command-line argument for reading and writing files to a program

I am trying to use my LoadTextFile() method to read a .txt file from the command prompt in Eclipse and then use another method, SaveDocumentsToJSON, to write into a json.file (again, the name of the json file should be entered as an argument in the command prompt).
My code
public static void main(String[] args) {
// instantiate an instance of the BTextLoader class.
BTextLoader loader = new BTextLoader();
// Check if command line arguments are NOT empty and then enter the file names.
if (args.length > 0) {
{
// with hard-coded loader.LoadTextFile("TextFile.txt") the next part of the code runs as expected.
for (int x = 0; x < args.length; x++) {
if (args[x].endsWith(".txt")) {
loader.LoadTextFile(args[x]);
}
if (args[x].endsWith(".json")) {
loader.SaveDocumentsToJSON(args[0]);
}
}
}
}
else {
System.err.println("No valid file was given.");
}
}
public void LoadTextFile(String filePath) {
try {
System.out.println("Loading file...");
File inFile = new File(filePath);
BufferedReader br = new BufferedReader(new FileReader(inFile));
String line = br.readLine();
Integer counter = 0;
while (line != null)
{
if (line.trim().length() > 0) {
documents.put("doc" + counter, line);
;
counter++;
}
line = br.readLine();
}
br.close();
} catch (Exception e) {
System.out.println("File Load Failed");
}
So if I enter the outputFile.json file in the command prompt, and hard code "TextFile.txt", then the result is as expected, with the text file remaining unaltered and a new .json file being created.
However, if I try to use loader.LoadTextFile(args[0]) and enter "TextFile.txt outputFile.json" (two file names with a space) in Eclipse, then my original TextFile.txt gets rewritten with a json structure and outputFile.json is not created.
I need help with loading my .txt file and then saving it with the names as command-line arguments. How can I avoid hard coding my .txt file for this to work?
Whatever parameter matches, you will always overwrite the first given file:
for (int x = 0; x < args.length; x++) {
if (args[x].endsWith(".json")) {
loader.SaveDocumentsToJSON(args[0]);
}
}
You need to change into
loader.SaveDocumentsToJSON(args[x]);
Yet there is still an imminent problem depending on the sequence of the parameters. Check how your code behaves if you first put the json file and afterwards the txt file. Similarly there is no check if you put several txt or json files. I'm wondering whether all that is intended or unplanned side effects.

How to change convert different csv files into standard format?

I have 2-3 .csv files with fields like Date, Amount, Transaction Description etc and all the csv files contains these fields but in shuffled order. I want a output file to with a standard order (like if I input the sample .csv file, then I can get the things in order in output file).
I tried to do it for one file by taking substrings from the .csv file (at that time I didn't know that other files have shuffled order fields).
I am kind of new, tell me if I am asking question in a good format!
Can I put a link for the sample input and output .csv file for the reference?
--> https://drive.google.com/drive/folders/1-NZi5OTMTbOWXAfCTsc-ahNYm1N5DG2g (just because it would be very hard to explain that how file looks like)
What I have done?
I have just tried to extract data from the fields using the BufferReader using split but it can only work for one type of file, I cant have a standard format using this!
Sorry for posting such a long code but what I have done is selected field from the file and copied them into output file corresponding to the standard fields in the output file.
Suggest me if there is any other method with which I can proceed.
File file = new File("C:\\Users\\R\\Desktop\\CSVDemo.csv");
try {
// create FileWriter object with file as parameter
FileWriter outputfile = new FileWriter(file);
CSVWriter writer = new CSVWriter(outputfile, ',',
CSVWriter.NO_QUOTE_CHARACTER,
CSVWriter.DEFAULT_ESCAPE_CHARACTER,
CSVWriter.DEFAULT_LINE_END);
// create a List which contains String array
String[] header = { "Date", "Transaction Description", "Debit","Credit","Currency","CardName","Transaction","Location" };
writer.writeNext(header);
String splitBy = ",";
BufferedReader br = new BufferedReader(new FileReader("G:\\US\\HDFC-Input-Case1.csv"));
String line;
String transaction = "",name = "";
while ((line = br.readLine()) != null) {
// use comma as separator
String[] cols = line.split(splitBy);
if(cols.length == 2 && cols[1].equals("Domestic Transactions")) {
transaction = "Domestic";
continue;
}
else if(cols.length == 2 && cols[1].equals("International Transactions")) {
transaction = "International";
continue;
}
else if(cols.length == 2) {
name = cols[1];
continue;
}
else if(cols.length<1){
continue;
}
else if(cols.length>2) {
if(cols[0].contains("Date")){
continue;
}
String[] data1 = new String[header.length];
data1[0] = cols[0];
String curr ;
if(cols[1].substring(cols[1].length()-3).equals("USD") || cols[1].substring(cols[1].length()-3).equals("EUR")) {
data1[4] = cols[1].substring(cols[1].length()-3);
curr = cols[1].substring(0,cols[1].length()-4);
data1[1] = curr;
}
else {
data1[4] = "INR";
data1[1] = cols[1];
}
if(cols[2].contains("cr")){
data1[3] = cols[2].substring(0,cols[2].length()-2);
data1[2] = "0";
}
else {
data1[2] = cols[2];
data1[3] = "0";
}
data1[5] = name;
data1[6] = transaction;
writer.writeNext(data1);
}
System.out.println();
}
// closing writer connection
writer.close();
}
You can read the header of your input csv files first and find the indexes of required field in this given csv file.
Once you have required indexes for every header, read those fields using indexes in the standard order you want for your output csv file.
sample codes:
`CSVReader reader = new CSVReader(new FileReader(fileName ));
String[] header = reader.readNext();
List<String> list= Arrays.asList(header);
int indexOfFieldTransaction=list.indexOf("transaction");`
Now make a List and insert the field in order you want to write in output file.you will get -1 if the field you are trying to get index of is not present in the input file.

Retrieve data from txt file and replace the data into a new txt file using java

I am trying to read in a text file and then manipulate a little and update the records into a new text file.
Here is what I have so far:
ArrayList<String> linesList = new ArrayList<>();
BufferedReader br;
String empid, email;
String[] data;
try {
String line;
br = new BufferedReader(new FileReader("file.txt"));
while ((line = br.readLine()) !=null) {
linesList.add(line);
}
br.close();
}
catch (IOException e) { e.printStackTrace(); }
for (int i = 0; i < linesList.size(); i++) {
data = linesList.get(i).split(",");
empid = data[0];
ccode = data[3];
}
File tempFile = new File("File2.txt");
BufferedWriter bw = new BufferedWriter(new FileWriter(tempFile));
for (int i = 0; i < linesList.size(); i++) {
if(i==0){
bw.write(linesList.get(i));
bw.newLine();
}
else{
data = linesList.get(i).split(",");
String empid1 = data[0];
if(data[13].equals("IND")) {
String replace = data[3].replaceAll("IND", "IN");
ccode1 = replace;
System.out.println(ccode1);
}
else if(data[13].equals("USA")) {
String replace = data[3].replaceAll("USA", "US");
ccode1 = replace;
}
else {
ccode1 = replace; //This does not work as replace is not defined here, but how can I get it to work here.
}
String newData=empid1+","+ccode1;
bw.write(newData);
bw.newLine();
}
}
Here is what is inside the text file:
EID,First,Last,Country
1,John,Smith,USA
2,Jane,Smith,IND
3,John,Adams,USA
So, what I need help with is editing the three letter country code and replacing it with a 2 letter country code. For example: USA would become US, and IND would become IN. I am able to read in the country code, but am having trouble in changing the value and then replacing the changed value back into a different text file. Any help is appreciated. Thanks in advance.
Open file in text editor, Search and Replace, ,USA with ,US, ,IND with ,IN and so on.
As such, to automate it, on the same while loop you read a line do:
//while(read){ line.replaceAll(",USA",",US");
That will be the easiest way to complete your objective.
To save, open a BufferedWriter bw; just like you opened a reader and use bw.write(). You would probably prefer to open both at the same time, the reader on your source file, and the writer on a new file, with _out suffix. That way you dont need to keep the file data in memory, you can read and write as you loop.
For harder ways, read the csv specs: https://www.rfc-editor.org/rfc/rfc4180#section-2
Notice that you have to account for the possibility of fields being enclosed in quotes, like: "1","John","Smith","USA", which means you also have to replace ,\"USA with ,\"US.
The delimiter may or may not be a comma, you have to make sure yur input will always use the same delimiter, or that you can detect and switch at runtime.
You have to account for the case where a delimiter may be part of a field, or where quotes are part of a field.
Now you know/can solve these issues you can, instead of using replace, parse the lines character by character using while( (/*int*/ c = br.read()) != -1), and do this replacement manually with an if gate.
/*while(read)*/
if( c == delimiter ){
if not field, start next field, else add to field value
} else if( c == quote ){
if field value empty, ignore and expect closing quote, else if quote escape not marked, mark it, else, add quote to field value
}
(...)
} else if( c == 13 or c == 10 ){
finished line, check last field of row read and replace data
}
To make it better/harder, define a parsing state machine, put the states into an Enum, and write the if gates with them in mind (this will make your code be more like a compiler parser).
You can find parsing code at different stages here: https://www.mkyong.com/java/how-to-read-and-parse-csv-file-in-java/
You need to change a little bit in your concept. If you want to edit a file then,
create a new file and write content in new file and delete old file and rename new file
with old name.
ArrayList<String> linesList = new ArrayList<>();
BufferedReader br;
String[] data;
File original=new File("D:\\abc\\file.txt");
try {
String line;
br = new BufferedReader(new FileReader(original));
while ((line = br.readLine()) !=null) {
linesList.add(line);
}
br.close();
}
catch (IOException e) { e.printStackTrace(); }
File tempFile = new File("D:\\abc\\tempfile.txt");
BufferedWriter bw = new BufferedWriter(new FileWriter(tempFile));
for (int i = 0; i < linesList.size(); i++) {
if(i==0){
bw.write(linesList.get(i));
bw.newLine();
}
else{
data = linesList.get(i).split(",");
String empid = data[0];
String name=data[1];
String lname=data[2];
String ccode = data[3].substring(0, 2);
String newData=empid+","+name+","+lname+","+ccode+"\n";
bw.write(newData);
bw.newLine();
}
}
bw.close();
if (!original.delete()) {
System.out.println("Could not delete file");
return;
}
// Rename the new file to the filename the original file had.
if (!tempFile.renameTo(original))
System.out.println("Could not rename file");

reading a txt file form External Storage Directory by one by eclipse Android

I have a .txt file in ExternalStorageDirectory() in Android. This file contains 10 sentence line by line. I want to read each sentence one by one. And then show it on EditText when every button click. I found only all file reading codes. I don't want this. How can I do that? Here is my little code:
enter cod private String Load() {
String result = null;;
String FILE_NAME = "counter.txt";
//if (isExternalStorageAvailable() && isExternalStorageReadOnly()) {
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "Records";
File file = new File(baseDir, FILE_NAME);
String line = "";
StringBuilder text = new StringBuilder();
try {
FileReader fReader = new FileReader(file);
BufferedReader bReader = new BufferedReader(fReader);
while( (line = bReader.readLine()) != null ){
text.append(line+"\n");
}
result = String.valueOf(text);
} catch (IOException e) {
e.printStackTrace();
}
//}
return result;
}
All Load() does is reads the file and returns it as a String. From here, you have a few options.
1).
Convert the result to an array of Strings using String.split('\n'), and grab the next value when you click the button. Here's a quick example:
int counter = 0;
String file = Load();
String[] lines = file.split("\n");
button.onClicked() {
editText.setText(lines[counter++]);
}
2).
Declare the buffered reader as a class member, so you can call readLine() inside the button's onClicked() method. This way, it will only read one line of the file when someone clicks the button, instead of reading the whole file in Load().

Get the offset of previous line in a file

I'm extracting data from a file line by line into a database and i can't figure out a proper way to flag lines that I've already read into my database.
I have the following code that I use to iterate through the file lines and I attempt to verify
that the line has my flag or else I try to append the flag to the file line
List<String> fileLines = new ArrayList<String>();
File logFile = new File("C:\\MyStuff\\SyslogCatchAllCopy.txt");
try {
RandomAccessFile raf = new RandomAccessFile(logFile, "rw");
String line = "";
String doneReadingFlag = "##";
Scanner fileScanner = new Scanner(logFile);
while ((line = raf.readLine()) != null && !line.contains(doneReading)) {
Scanner s = new Scanner(line);
String temp = "";
if (!s.hasNext(doneReadingFlag)) {
fileLines.add(line);
raf.write(doneReadingFlag.getBytes(), (int) raf.getFilePointer(),
doneReadingFlag.getBytes().length);
} else {
System.err.println("Allready Red");
}
}
} catch (FileNotFoundException e) {
System.out.println("File not found" + e);
} catch (IOException e) {
System.out.println("Exception while reading the file ");
}
// return fileLines;
// MoreProccessing(fileLines);
This code appends the flag to the next line and it overwrites the characters in that position
Any Help ?
When you write to a file, it doesn't insert do you should expect it to replace the characters.
You need to reserve space in the file for information you want to change or you can add information to another file.
Or instead of marking each file, you can store somewhere the lines number (or better the character position) you have read up to.
If you are not restarting your process you can have process read the file as it is appended (meaning you might not need to store where you are up to anywhere)
#Peter Lawrey I did as you said and it worked for me like that:
as follows:
ArrayList<String> fileLines=new ArrayList<String>();
File logFile=new File("C:\\MyStuff\\MyFile.txt");
RandomAccessFile raf = new RandomAccessFile(logFile, "rw");
String line="";
String doneReadingFlag="#";
long oldOffset=raf.getFilePointer();
long newOffset=oldOffset;
while ((line=raf.readLine())!=null)
{
newOffset=raf.getFilePointer();
if(!line.contains(doneReadingFlag))
{
fileLines.add(line);
raf.seek((long)oldOffset);
raf.writeChars(doneReadingFlag);
raf.seek(newOffset);
System.out.println("Line added and flaged");
}
else
{
System.err.println("Already Red");
}
oldOffset=newOffset;
}

Categories