I have a CSV file which reads this.
City,Job,Salary
Delhi,Doctors,500
Delhi,Lawyers,400
Delhi,Plumbers,100
London,Doctors,800
London,Lawyers,700
London,Plumbers,300
Tokyo,Doctors,900
Tokyo,Lawyers,800
Tokyo,Plumbers,400
Lawyers,Doctors,300
Lawyers,Lawyers,400
Lawyers,Plumbers,500
Hong Kong,Doctors,1800
Hong Kong,Lawyers,1100
Hong Kong,Plumbers,1000
Moscow,Doctors,300
Moscow,Lawyers,200
Moscow,Plumbers,100
Berlin,Doctors,800
Berlin,Plumbers,900
Paris,Doctors,900
Paris,Lawyers,800
Paris,Plumbers,500
Paris,Dog catchers,400`
Now, I want to sort the column of Salary and write it to a txt file.
I can access the column, but not able to sort it. I am new to this CSV Reading part of Java. Can someone help! How should I store each salary value to a variable.
import java.io.*;
public class Main {
public static void main(String args[]) throws FileNotFoundException
{
String csv="C:\\Users\\Dipayan\\Desktop\\salaries.csv";
BufferedReader br= new BufferedReader(new FileReader(csv));
String line="";
try {
br.readLine();
while((line = br.readLine())!=null)
{
String[] f=line.split(",");
System.out.println(" Salary ="+f[2]);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
You can try something like -
String csv="/home/user/Desktop/salaries.csv";
BufferedReader br= new BufferedReader(new FileReader(csv));
String line;
Map<Integer, String> salaryMap = new TreeMap<Integer, String>();
try {
br.readLine();
while((line = br.readLine()) != null) {
salaryMap.put(Integer.parseInt(line.split(",")[2]), line);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
FileWriter fw = new FileWriter("/home/user/Desktop/salaries.txt");
BufferedWriter bw = new BufferedWriter(fw);
List<String> list = new ArrayList<String>(salaryMap.values());
for (String str : list) {
bw.write(str);
bw.newLine();
}
bw.flush();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
I think you should use map here or may be
List<Integer, String>
In case of map
Map<Integer,String>
where key would be the salary and the string would be the whole complete row.
Let me write some code to help you.
Map<Integer,String> dataMap = new HashMap<Integer,String>();
String row = br.readLine();
String columns[]=row.split(","); // columns[2] has the salary now
dataMap.add(Integer.valueOf(columns[2]),row);
Use bubble sort to saw the content or your customer compare class to sort the map. Check what are the possible sort functions of Collection Api.
You can use even List<Integer,String>
Sort with respect to integer, keep placing the elements on their actual positions and re-generate the file.
EDIT:
You can use tree map since it sorts the data. Just use Treemap of integer as key and string as the value. Put all the values in it and iterate over it, that's all!
Be careful with the map, put will override your previous values.
You can use Arrays.sort that will sort a native array or use guavas Iterables.sortedCopy
Here´s a codebank for Arrays.sort: http://codebunk.com/b/40731608/
Java NIO
Java has provided a second I/O system called NIO (New I/O).
NIO was developed to allow Java programmers to implement high-speed I/O without using the custom native code. NIO moves the time-taking I/O activities like filling, namely and draining buffers, etc back into the operating system, thus allows for a great increase in operational speed.
import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
// ...
Path filePath = new File("csv_file_path").toPath();
Charset charset = Charset.defaultCharset();
List<String> stringList = Files.readAllLines(filePath, charset);
String[] stringArray = stringList.toArray(new String[]{});
Arrays.sort(stringArray, new Comparator<String>(){
public int compare(String first, String second) {
return Integer.valueOf(first.split(",")[2]).compareTo(Integer.valueOf(second.split(",")[2]));
}
});
for (String newstr: stringArray){
System.out.println(newstr);
}
Packages Used in Above Code: -
java.nio.charset :- It encapsulates the character sets and also supports encoders and decoders operation that convert characters to bytes and bytes to characters, respectively.
java.nio.file :- It provides the support for files.
Methods Used: -
toPath() :- (No parameters)
This method returns a java.nio.file.Path object constructed from the this abstract path.
Exception:- InvalidPathException – if a Path object cannot be constructed from the abstract path (see FileSystem.getPath)
Example: -
File file = new File("C:\\sandbox\\test.txt");
System.out.println(file.toPath());
Output:- C:\sandbox\test.txt
Note:- It is mandatory to add an exception for above code
defaultCharset() : - (No parameters)
This method returns the default charset of this Java virtual machine.
public static List <String> readAllLines(Path path, Charset cs) :-
Parameters (path - the path to the file, cs - the charset to use for decoding)
This method read all the lines from the file as a List.
Now, I have converted the List into an Array using toArray() method and implemented a Comparator for sorting an array.
I have overridden the compare method and comparing two strings which are the third string in each sentence after comma(,) and converting them to a number and arranging them in a sorted order.
Related
I use Android Studio.I have a text file with some of numbers and I want to calculate them with others numbers. When I am try to convert them from string with method Integer.parseInt on program start I get error and program close.Error is :
at java.lang.Integer.parseInt(Integer.java:521)
at java.lang.Integer.parseInt(Integer.java:556)
I am just beginner and sorry for bad english , I hope you understand my problem.
This is part of my code.
public void read (){
try {
FileInputStream fileInput = openFileInput("example.txt");
InputStreamReader reader = new InputStreamReader(fileInput);
BufferedReader buffer = new BufferedReader(reader);
StringBuffer strBuffer = new StringBuffer();
String lines;
while ((lines = buffer.readLine()) != null) {
strBuffer.append(lines + "\n");
}
int numbers = Integer.parseInt(strBuffer.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Here:
int numbers = Integer.parseInt(strBuffer.toString());
You should read the javadoc for the library methods you are using. parseInt() parses one number from a string that contains one number.
So you need
to learn how to use arrays of int (because you want to read and process multiple numbers), not just a single one
to then use parseInt() on the individual number strings in that file
Also note that you can use the Scanner to directly work on an InputStream, there is no need to first turn the complete file content into one large string in memory!
Integer.parseInt(String) throws a NumberFormatException when its argument can't be converted to a number.
Break your problem into smaller, more manageable blocks. Your code currently gets the entire content of example.txt and tries to parse the whole thing to an Integer.
One possibility for reading all integer values is to do this with a java.util.Scanner object instead and use its nextInt() method.
Consider the following example, given a file example.txt with integers separated by spaces.
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class App {
public static void main(String...args) throws Exception {
File file = new File("/home/william/example.txt");
try (InputStream is = Files.newInputStream(file.toPath())) {
Scanner scanner = new Scanner(is);
List<Integer> ints = new ArrayList<>();
while (scanner.hasNextInt()) {
int i = scanner.nextInt();
System.out.printf("Read %d%n", i);
ints.add(i);
}
}
}
}
China-中国,CN
Angola-安哥拉,AO
Afghanistan-阿富汗,AF
Albania-阿尔巴尼亚,AL
Algeria-阿尔及利亚,DZ
Andorra-安道尔共和国,AD
Anguilla-安圭拉岛,AI
In Java, I'm reading the above text from a file and creating a map where the keys will be the part before the comma and the values will be the region code after the comma.
Here is the code:
public static void main(String[] args) {
BufferedReader br;
Map<String,String> mymap = new HashMap<String,String>();
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream("C:/Users/IBM_ADMIN/Desktop/region_code_abbreviations_Chinese.csv"), "UTF-8"));
String line;
while ((line = br.readLine()) != null) {
//System.out.println(line);
String[] arr= line.split(",");
mymap.put(arr[0], arr[1]);
}
br.close();
} catch (IOException e) {
System.out.println("Failed to read users file.");
} finally {}
for(String s: mymap.keySet()){
System.out.println(s);
if(s.equals("China-中国")){
System.out.println("Got it");
break;
}
}
System.out.println("----------------");
System.out.println("Returned from map "+ mymap.get("China-中国"));
mymap = new HashMap<String,String>();
mymap.put("China-中国","Explicitly Put");
System.out.println(mymap.get("China-中国"));
System.out.println("done");
}
The output:
:
:
Egypt-埃及
Guyana-圭亚那
New Zealand-新西兰
China-中国
Indonesia-印度尼西亚
Laos-老挝
Chad-乍得
Korea-韩国
:
:
Returned from map null
Explicitly Put
done
Map is loaded correctly but when I search the map for "China-中国" - I do not get the value.
If I explicitly put "China-中国" in map, then it returns a value.
Why is this happening?
Check if your resource file is not UTF-8, e.g. UTF-8Y, with BOM Bytes at the start. But this would only infere with the first value. If you change the test to a value from the middle, do you have a value or not? If not then this is not the problem.
Second possibility is your source code file is not UTF-8. Therefore the byte sequence of "China-中国" of your resource file and your sourcecode file is not equal and you will not get a match. But you include the value with the sourcecodes byte sequence explicitly and it will be found.
In fact this is not a problem with HashMap but with character or file encoding.
Since you are having a problem with the first value, I would check to see if the file starts with a BOM (Byte Order Mark).
If so, try stripping the BOM before processing.
See: Byte order mark screws up file reading in Java
You can use org.apache.commons.io.input.BOMInputStream.
BufferedReader br= new BufferedReader(new InputStreamReader(new BOMInputStream(new FileInputStream("filepath")),"UTF-8"))
with this problem I have, I'd like to hit two birds with one stone.
I'm currently trying to output user input from text fields into an existing .CSV file with data already residing within. My first problem stems from not being able to append to a new line, my code is currently appending to the last item in the .CSV file, thus creating an even longer line, not a new line.
Next, I would like to check my .CSV for possible duplicates of the users input. If a user wants to add a Banana to the list, and code checks through the .CSV file and finds a banana within the file, then we can successfully throw an error and warn the user.
Here's my code currently to attempt to try and append to a new line, but somehow it's just not working:
String fileName = "temp.csv";
try {
FileWriter fileWriter =
new FileWriter(fileName, true);
BufferedWriter bufferedWriter =
new BufferedWriter(fileWriter);
bufferedWriter.write("\n" + fruitNameField.getText());
bufferedWriter.write(',');
bufferedWriter.write(quantityOfFruitField.getText());
bufferedWriter.write(',');
bufferedWriter.write(fruitLocationField.getText());
//bufferedWriter.write(',');
bufferedWriter.close();
}
catch(IOException ex)
{
System.out.println("Error writing to file" + fileName + "'");
}
While I am wanting 3 different user inputs and to append to a new line, the code above ends up outputting like this: Banana,2,storeOrange,3,store. It seems to be ignoring the new line command.
Now for my second problem, checking against duplicates. For the life of me, I cannot find any resources relating to checking for duplicates within a text file using java.
This question is mainly for appending to a new line, but if I could get any help on this, that would be amazing.
To my knowledge, in order to check for duplicates, I believe I'd have to import my text file and write it to an array, but what if it's a big file?
Once my file is in an array, I'll check if the user input is equal to any text residing within the array, and if it is, throw an error. That is my approach on this subject, please tell me if I can improve on this any way.
Thanks for your help, much appreciated.
I would suggest to make use of a library like opencsv to read and write to csv files.
Example:
import com.opencsv.CSVReader;
import com.opencsv.CSVWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class JavaApplication28 {
public static void main(String[] args) throws IOException {
String input = fruitNameField.getText();
String filename = "temp.csv";
writeToCsvFile(input,filename);
}
private static void writeToCsvFile(String input, String filename) throws IOException {
if(!isDuplicate(input,filename)){
CSVWriter writer = new CSVWriter(new FileWriter(filename,true), ',');
String[] entries = {fruitNameField.getText(),quantityOfFruitField.getText(),fruitLocationField.getText()};
writer.writeNext(entries);
writer.close();
}
else{
System.out.println("fruitName already exists.");
}
}
private static boolean isDuplicate(String input, String filename) throws IOException {
boolean found = false;
CSVReader reader = new CSVReader(new FileReader(filename));
String [] nextLine;
while ((nextLine = reader.readNext()) != null) {
for(int i = 0; i<nextLine.length; i++){
if(nextLine[i].equalsIgnoreCase(input)){
found = true;
break;
}
}
}
return found;
}
}
If the file is not enormously big, I would suggest to read the whole file and store it in a Map whose keys are the words you're adding(which you want to check for duplicates).
On every new line, you can check whether the map contains the key(which costs only O(1) so it's highly efficient).
For the newlines, note that it depends on the environment, it may be \r\n (for Windows) or \n for Unix/Mac OS. Best is to use System.getProperty("line.separator");
I'm reading numbers from a txt file using BufferedReader for analysis. The way I'm going about this now is- reading a line using .readline, splitting this string into an array of strings using .split
public InputFile () {
fileIn = null;
//stuff here
fileIn = new FileReader((filename + ".txt"));
buffIn = new BufferedReader(fileIn);
return;
//stuff here
}
public String ReadBigStringIn() {
String line = null;
try { line = buffIn.readLine(); }
catch(IOException e){};
return line;
}
public ProcessMain() {
initComponents();
String[] stringArray;
String line;
try {
InputFile stringIn = new InputFile();
line = stringIn.ReadBigStringIn();
stringArray = line.split("[^0-9.+Ee-]+");
// analysis etc.
}
}
This works fine, but what if the txt file has multiple lines of text? Is there a way to output a single long string, or perhaps another way of doing it? Maybe use while(buffIn.readline != null) {}? Not sure how to implement this.
Ideas appreciated,
thanks.
You are right, a loop would be needed here.
The usual idiom (using only plain Java) is something like this:
public String ReadBigStringIn(BufferedReader buffIn) throws IOException {
StringBuilder everything = new StringBuilder();
String line;
while( (line = buffIn.readLine()) != null) {
everything.append(line);
}
return everything.toString();
}
This removes the line breaks - if you want to retain them, don't use the readLine() method, but simply read into a char[] instead (and append this to your StringBuilder).
Please note that this loop will run until the stream ends (and will block if it doesn't end), so if you need a different condition to finish the loop, implement it in there.
I would strongly advice using library here but since Java 8 you can do this also using streams.
try (InputStreamReader in = new InputStreamReader(System.in);
BufferedReader buffer = new BufferedReader(in)) {
final String fileAsText = buffer.lines().collect(Collectors.joining());
System.out.println(fileAsText);
} catch (Exception e) {
e.printStackTrace();
}
You can notice also that it is pretty effective as joining is using StringBuilder internally.
If you just want to read the entirety of a file into a string, I suggest you use Guava's Files class:
String text = Files.toString("filename.txt", Charsets.UTF_8);
Of course, that's assuming you want to maintain the linebreaks. If you want to remove the linebreaks, you could either load it that way and then use String.replace, or you could use Guava again:
List<String> lines = Files.readLines(new File("filename.txt"), Charsets.UTF_8);
String joined = Joiner.on("").join(lines);
Sounds like you want Apache IO FileUtils
String text = FileUtils.readStringFromFile(new File(filename + ".txt"));
String[] stringArray = text.split("[^0-9.+Ee-]+");
If you create a StringBuilder, then you can append every line to it, and return the String using toString() at the end.
You can replace your ReadBigStringIn() with
public String ReadBigStringIn() {
StringBuilder b = new StringBuilder();
try {
String line = buffIn.readLine();
while (line != null) {
b.append(line);
line = buffIn.readLine();
}
}
catch(IOException e){};
return b.toString();
}
You have a file containing doubles. Looks like you have more than one number per line, and may have multiple lines.
Simplest thing to do is read lines in a while loop.
You could return null from your ReadBigStringIn method when last line is reached and terminate your loop there.
But more normal would be to create and use the reader in one method. Perhaps you could change to a method which reads the file and returns an array or list of doubles.
BTW, could you simply split your strings by whitespace?
Reading a whole file into a single String may suit your particular case, but be aware that it could cause a memory explosion if your file was very large. Streaming approach is generally safer for such i/o.
This creates a long string, every line is seprateted from string " " (one space):
public String ReadBigStringIn() {
StringBuffer line = new StringBuffer();
try {
while(buffIn.ready()) {
line.append(" " + buffIn.readLine());
} catch(IOException e){
e.printStackTrace();
}
return line.toString();
}
I want to read a text file containing space separated values. Values are integers.
How can I read it and put it in an array list?
Here is an example of contents of the text file:
1 62 4 55 5 6 77
I want to have it in an arraylist as [1, 62, 4, 55, 5, 6, 77]. How can I do it in Java?
You can use Files#readAllLines() to get all lines of a text file into a List<String>.
for (String line : Files.readAllLines(Paths.get("/path/to/file.txt"))) {
// ...
}
Tutorial: Basic I/O > File I/O > Reading, Writing and Creating text files
You can use String#split() to split a String in parts based on a regular expression.
for (String part : line.split("\\s+")) {
// ...
}
Tutorial: Numbers and Strings > Strings > Manipulating Characters in a String
You can use Integer#valueOf() to convert a String into an Integer.
Integer i = Integer.valueOf(part);
Tutorial: Numbers and Strings > Strings > Converting between Numbers and Strings
You can use List#add() to add an element to a List.
numbers.add(i);
Tutorial: Interfaces > The List Interface
So, in a nutshell (assuming that the file doesn't have empty lines nor trailing/leading whitespace).
List<Integer> numbers = new ArrayList<>();
for (String line : Files.readAllLines(Paths.get("/path/to/file.txt"))) {
for (String part : line.split("\\s+")) {
Integer i = Integer.valueOf(part);
numbers.add(i);
}
}
If you happen to be at Java 8 already, then you can even use Stream API for this, starting with Files#lines().
List<Integer> numbers = Files.lines(Paths.get("/path/to/test.txt"))
.map(line -> line.split("\\s+")).flatMap(Arrays::stream)
.map(Integer::valueOf)
.collect(Collectors.toList());
Tutorial: Processing data with Java 8 streams
Java 1.5 introduced the Scanner class for handling input from file and streams.
It is used for getting integers from a file and would look something like this:
List<Integer> integers = new ArrayList<Integer>();
Scanner fileScanner = new Scanner(new File("c:\\file.txt"));
while (fileScanner.hasNextInt()){
integers.add(fileScanner.nextInt());
}
Check the API though. There are many more options for dealing with different types of input sources, differing delimiters, and differing data types.
This example code shows you how to read file in Java.
import java.io.*;
/**
* This example code shows you how to read file in Java
*
* IN MY CASE RAILWAY IS MY TEXT FILE WHICH I WANT TO DISPLAY YOU CHANGE WITH YOUR OWN
*/
public class ReadFileExample
{
public static void main(String[] args)
{
System.out.println("Reading File from Java code");
//Name of the file
String fileName="RAILWAY.txt";
try{
//Create object of FileReader
FileReader inputFile = new FileReader(fileName);
//Instantiate the BufferedReader Class
BufferedReader bufferReader = new BufferedReader(inputFile);
//Variable to hold the one line data
String line;
// Read file line by line and print on the console
while ((line = bufferReader.readLine()) != null) {
System.out.println(line);
}
//Close the buffer reader
bufferReader.close();
}catch(Exception e){
System.out.println("Error while reading file line by line:" + e.getMessage());
}
}
}
Look at this example, and try to do your own:
import java.io.*;
public class ReadFile {
public static void main(String[] args){
String string = "";
String file = "textFile.txt";
// Reading
try{
InputStream ips = new FileInputStream(file);
InputStreamReader ipsr = new InputStreamReader(ips);
BufferedReader br = new BufferedReader(ipsr);
String line;
while ((line = br.readLine()) != null){
System.out.println(line);
string += line + "\n";
}
br.close();
}
catch (Exception e){
System.out.println(e.toString());
}
// Writing
try {
FileWriter fw = new FileWriter (file);
BufferedWriter bw = new BufferedWriter (fw);
PrintWriter fileOut = new PrintWriter (bw);
fileOut.println (string+"\n test of read and write !!");
fileOut.close();
System.out.println("the file " + file + " is created!");
}
catch (Exception e){
System.out.println(e.toString());
}
}
}
Just for fun, here's what I'd probably do in a real project, where I'm already using all my favourite libraries (in this case Guava, formerly known as Google Collections).
String text = Files.toString(new File("textfile.txt"), Charsets.UTF_8);
List<Integer> list = Lists.newArrayList();
for (String s : text.split("\\s")) {
list.add(Integer.valueOf(s));
}
Benefit: Not much own code to maintain (contrast with e.g. this). Edit: Although it is worth noting that in this case tschaible's Scanner solution doesn't have any more code!
Drawback: you obviously may not want to add new library dependencies just for this. (Then again, you'd be silly not to make use of Guava in your projects. ;-)
Use Apache Commons (IO and Lang) for simple/common things like this.
Imports:
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
Code:
String contents = FileUtils.readFileToString(new File("path/to/your/file.txt"));
String[] array = ArrayUtils.toArray(contents.split(" "));
Done.
Using Java 7 to read files with NIO.2
Import these packages:
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
This is the process to read a file:
Path file = Paths.get("C:\\Java\\file.txt");
if(Files.exists(file) && Files.isReadable(file)) {
try {
// File reader
BufferedReader reader = Files.newBufferedReader(file, Charset.defaultCharset());
String line;
// read each line
while((line = reader.readLine()) != null) {
System.out.println(line);
// tokenize each number
StringTokenizer tokenizer = new StringTokenizer(line, " ");
while (tokenizer.hasMoreElements()) {
// parse each integer in file
int element = Integer.parseInt(tokenizer.nextToken());
}
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
To read all lines of a file at once:
Path file = Paths.get("C:\\Java\\file.txt");
List<String> lines = Files.readAllLines(file, StandardCharsets.UTF_8);
All the answers so far given involve reading the file line by line, taking the line in as a String, and then processing the String.
There is no question that this is the easiest approach to understand, and if the file is fairly short (say, tens of thousands of lines), it'll also be acceptable in terms of efficiency. But if the file is long, it's a very inefficient way to do it, for two reasons:
Every character gets processed twice, once in constructing the String, and once in processing it.
The garbage collector will not be your friend if there are lots of lines in the file. You're constructing a new String for each line, and then throwing it away when you move to the next line. The garbage collector will eventually have to dispose of all these String objects that you don't want any more. Someone's got to clean up after you.
If you care about speed, you are much better off reading a block of data and then processing it byte by byte rather than line by line. Every time you come to the end of a number, you add it to the List you're building.
It will come out something like this:
private List<Integer> readIntegers(File file) throws IOException {
List<Integer> result = new ArrayList<>();
RandomAccessFile raf = new RandomAccessFile(file, "r");
byte buf[] = new byte[16 * 1024];
final FileChannel ch = raf.getChannel();
int fileLength = (int) ch.size();
final MappedByteBuffer mb = ch.map(FileChannel.MapMode.READ_ONLY, 0,
fileLength);
int acc = 0;
while (mb.hasRemaining()) {
int len = Math.min(mb.remaining(), buf.length);
mb.get(buf, 0, len);
for (int i = 0; i < len; i++)
if ((buf[i] >= 48) && (buf[i] <= 57))
acc = acc * 10 + buf[i] - 48;
else {
result.add(acc);
acc = 0;
}
}
ch.close();
raf.close();
return result;
}
The code above assumes that this is ASCII (though it could be easily tweaked for other encodings), and that anything that isn't a digit (in particular, a space or a newline) represents a boundary between digits. It also assumes that the file ends with a non-digit (in practice, that the last line ends with a newline), though, again, it could be tweaked to deal with the case where it doesn't.
It's much, much faster than any of the String-based approaches also given as answers to this question. There is a detailed investigation of a very similar issue in this question. You'll see there that there's the possibility of improving it still further if you want to go down the multi-threaded line.
read the file and then do whatever you want
java8
Files.lines(Paths.get("c://lines.txt")).collect(Collectors.toList());