读入 csv 后修改指定位置数据再写出
【问题】
tl;dr: I want to output my HashMap
in the same CSV file format that I am reading it in.
I want to preface this with: I may be going about this the wrong way. Because I started this thinking one thing and didn’t account for this problem I’m having. So I’m trying to make a small application that will give you a random movie to watch depending on what genre you are in the mood for (similarly to Netflix’s Max application, but considerably dumbed down). I have a list of movies that I’m going to format myself in CSV format, because I recently wrote some code that reads in values from a CSV file and I didn’t have much to alter.
Here is the dilemma: I have read in the CSV formatted file (only a two line sample file), since I know what columns contain what I use a BufferedReader
to read in line by line storing each value of the delimited value in its own ArrayList
(I know there is a better way but this is what I came up with for now) I then store each ArrayList
according to genre into a HashMap
. Now I want to be able to write back out to the same file at some point to edit it. So movies that have been watched will be removed from the HashMap
and then overwrite the file, so that when it’s read back in next time the movie that was already watched will not be in the file anymore. So the difficulty I am having at this point is formatting the output back out to account for empty spaces in the actual CSV.
So for example, the test file I have only contains two lines where each movie genre has two movies except for drama and comedy. So the file looks like this
Action,Drama,Sci-fi/Fantasy,Thriller/Suspense,Comedy Action2,,Sci-fi/Fantasy2,Thriller/Suspense2,
Just to solidify what output I want/expected; Say I watch Sci-fi/Fantasy2, it was a good movie, but it's gotta go, the output I want once removed is this
Action,Drama,Sci-fi/Fantasy,Thriller/Suspense,Comedy Action2,,,Thriller/Suspense2,
But I know I'm not going to get those results because when I simply read the file then output it back out I get:
Action,Action2, Drama,, Thriller/Suspense,Thriller/Suspense2, Comedy,, Sci-fi/Fantasy,Sci-fi/Fantasy2,
So after getting these results I now realize I didn't plan well enough, and wonder if I'm going about this the wrong way. Does anyone know how to format in the way I described? I tried to find a solution, but after coming up empty handed I deduced that maybe the format I want goes against how a CSV should look, considering some cells in the file would have to be blank. I tried keeping any blank spaces from the file so they would go into the hashmap, but results were the same. I thought about bypassing the output file altogether, but I'm not sure how to save the values I originally read in that go into my map. Any ideas or solutions would greatly appreciated. Here is the class that does all the work:
package rngesus;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
public class ReadWrite {
private static final String[] GENRES = { "Action", "Drama",
"Sci-Fi/Fantasy", "Thriller/Suspense", "Comedy" };
private static final String NEW_LINE = "\n";
private static final String DELIMITER = ",";
private static final int NUM_OF_COL = 5;
private static final int GENRE_1 = 0;
private static final int GENRE_2 = 1;
private static final int GENRE_3 = 2;
private static final int GENRE_4 = 3;
private static final int GENRE_5 = 4;
private static String moviesFile;
private HashMap<String, ArrayList<String>> moviesByGenre;
ArrayList<String> actionMovies;
ArrayList<String> dramaMovies;
ArrayList<String> sciFiFantasyMovies;
ArrayList<String> thrillerSuspenseMovies;
ArrayList<String> comedyMovies;
public ReadWrite() {
moviesFile = "";
moviesByGenre = new HashMap<String, ArrayList<String>>();
actionMovies = new ArrayList<String>();
dramaMovies = new ArrayList<String>();
sciFiFantasyMovies = new ArrayList<String>();
thrillerSuspenseMovies = new ArrayList<String>();
comedyMovies = new ArrayList<String>();
}
public void readAndSortInputFile(String fileOfMovies) throws IOException {
try {
BufferedReader buffRdr = new BufferedReader(new FileReader(
new File(fileOfMovies)));
String line = "";
while ((line = buffRdr.readLine()) != null) {
String[] lnPtr = line.split(",", NUM_OF_COL);
int diff = Math.min(lnPtr.length, NUM_OF_COL);
for (int i = 0; i < diff; i++) {
if ((i == GENRE_1) && !lnPtr[i].isEmpty()) {
actionMovies.add(lnPtr[i]);
} else if ((i == GENRE_2) && !lnPtr[i].isEmpty()) {
dramaMovies.add(lnPtr[i]);
} else if ((i == GENRE_3) && !lnPtr[i].isEmpty()) {
sciFiFantasyMovies.add(lnPtr[i]);
} else if ((i == GENRE_4) && !lnPtr[i].isEmpty()) {
thrillerSuspenseMovies.add(lnPtr[i]);
} else if ((i == GENRE_5) && !lnPtr[i].isEmpty()){
comedyMovies.add(lnPtr[i]);
}
}
【回答】
该问题看起来就是修改csv文件中指定行列的内容,做起来并不难,只是Java写起来会很繁琐,用SPL就简单的多:
A |
|
1 |
=file("d:\\source.csv").import@c() |
2 |
=A1.modify(2,null:#3) |
3 |
=file("d:\\source.csv").export@c(A1) |
A1:读取source.csv中的内容。
A2:将第2行的第3列数据改成null。
A3:将修改后的A1的结果再写入source.csv文件。
这段代码可以方便地集成进Java(可参考Java 如何调用 SPL 脚本)。