I am trying to assign values in a file using a comma as a delimiter. The problem arises after the first line, because there is no comma at the end of the first line, so the Scanner is reading the last object of the first line and the first object of the second line as one single object. How do I tell the Scanner to only read the line?
The link to the file I am reading is: ftp://webftp.vancouver.ca/OpenData/csv/schools.csv
String schoolURL = ("ftp://webftp.vancouver.ca/OpenData/csv/schools.csv");
URL url = new URL(schoolURL);
Scanner sc2 = new Scanner(url.openStream()).useDelimiter(",");
//The file I am trying to read has a header line as the first line, hence the sc2.nextLine() being at the top of the for loop.//
for(int i=0; sc2.hasNextLine(); i++) {
sc2.nextLine();
String name, add, website;
double lat, longi;
name = sc2.next();
lat=Double.parseDouble(sc2.next());
longi=Double.parseDouble(sc2.next());
add=sc2.next();
website=sc2.next();
schools[i] = new School(name, lat, longi, add, website);
}
When it should be an implementation based on java.util.Scanner, you should make it to accept also the end of a line as another delimiter, in addition to comma.
If I get the Pattern definition right, the instantiation of Scanner should be:
Scanner sc2 = new Scanner( url.openStream() ).useDelimiter( ",|\\R" );
The \R stands for
Linebreak matcher: Any Unicode linebreak sequence, is equivalent to
\u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]
Refer to the documentation for java.util.regex.Pattern for the details.
Alternative way is use BufferedReader
As say #Yannis Rizos first read line then split it:
Java 7
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import static java.lang.Double.parseDouble;
public class App {
private static final String SOURCE_URL = "ftp://webftp.vancouver.ca/OpenData/csv/schools.csv";
private static final int SCHOOL = 0;
private static final int LATITUDE = 1;
private static final int LONGITUDE = 2;
private static final int ADDRESS = 3;
private static final int WEBSITE = 4;
public static void main(String[] args) {
boolean isHeader = true;
List<School> schools = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(SOURCE_URL).openStream()))) {
for (String line; (line = reader.readLine()) != null; ) {
if (isHeader) {
isHeader = false;
}
else {
String[] snippets = line.split(",");
// Class a School have next constructor signature
// public School(String name, double latitude, double longitude, String address, String webSite)
schools.add(new School(
snippets[SCHOOL],
parseDouble(snippets[LATITUDE]),
parseDouble(snippets[LONGITUDE]),
snippets[ADDRESS],
snippets[WEBSITE]
));
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Java 8
List<School> schools = Files.lines(Paths.get(SOURCE_URL))
.skip(1) // skip header
.map(line -> line.split(","))
.map(snippets -> new School(
snippets[SCHOOL],
parseDouble(snippets[LATITUDE]),
parseDouble(snippets[LONGITUDE]),
snippets[ADDRESS],
snippets[WEBSITE]
))
.collect(Collectors.toList());
As result you will have collections of 113 schools.
Related
Find string inside of a text file. Then get the following line and split by indexOf() and substring().
import java.util.*;
import java.io.*;
public class FileReadTest {
public static void main(String[] args) throws IOException {
File f = new File("a.dat");
Scanner fin = new Scanner(f);
String airportcode = "HOI";
while (fin.hasNextLine()) {
String line = fin.nextLine();
int firstindex = line.indexOf(airportcode);
if (firstindex > 0) {
int Code = line.indexOf("|");
int Country = line.lastIndexOf("|",Code);
int State = line.indexOf("|", Country);
int City = line.indexOf("|", State);
int Airport = line.indexOf("|", City);
System.out.println(Code);
System.out.println(Country);
System.out.println(State);
System.out.println(City);
System.out.println(Airport);
System.out.println(line.substring(0, Code));
break;
}
}
fin.close();
}
}
The 1 sout looks like this:
French Polynesia|HOI|Hao|Tuamotos|Hao Airport
I need using only indexOf() and substring(),
but I need it like this:
French Polynesia
HOI
Hao
Tuamotos
Hao Airport
What should I do?
Starting from the assumption you always the same number of fields, in your case 5 separated by the character | you can solve the problem without using String split method but just indexOf and substring like below:
String s = "French Polynesia|HOI|Hao|Tuamotos|Hao Airport";
for (int i = 0; i < 4; ++i) {
int endIndex = s.indexOf("|");
System.out.println(s.substring(0, endIndex));
s = s.substring(endIndex + 1);
}
System.out.println(s);
The code will print all the fields that can be assigned to your distinct variables.
Assuming that:
file content has lines with the following structure: French Polynesia|HOI|Hao|Tuamotos|Hao Airport
you need to print only those lines that contain "HOI" string
you have to use indexOf and substring only.
Here is code snippet that should work for you (file a.dat is located in resources folder):
package example;
import java.util.*; // for Scanner
import java.io.*; // for File and IOException
public class FileReadTest {
public static void main(String[] args) throws IOException {
File f = new File(
Objects.requireNonNull(FileReadTest.class.getClassLoader().getResource("a.dat")).getFile()
);
Scanner fin = new Scanner(f);
String airportcode = "HOI";
while (fin.hasNextLine()) {
String line = fin.nextLine();
if (line.indexOf(airportcode) != -1) {
int firstindex;
while ((firstindex = line.indexOf("|")) != -1) {
System.out.println(line.substring(0, firstindex));
line = line.substring(firstindex + 1);
}
System.out.println(line); // last data
}
}
}
}
it's showing null exception. what to do now?
import java.io.File;
import java.util.Scanner;
public class Quiz1 {
public static void main(String[] args) {
File f = new File("QuizMark.txt");
try{
Scanner s = new Scanner (f);
QuizMark[] p = new QuizMark[10];
while(s.hasNext()==true)
{
int c = s.nextInt();
double d = s.nextInt();
for(int i=0;i<10;i++){
p[i]= new QuizMark(c,d);
System.out.println(p[i].getId());
System.out.println(p[i].getScore());
i++;
}
}
}
catch(Exception e){
System.out.println(e.getMessage());
}
}
}
First of all your file must define a pattern of data saved in it like marks and id Separated by commas or hyphens underscores etc whatever you like to save pattern.Each next data should be on next line.Then read the text in proper manner as you saved in file.
Example QuizMarks.txt
01,96.5
02,78.9
03,65
04,89.7
Java Code
int count = 0;
String s[];
String line="";
QuizMark[] p = new QuizMark[10];
BufferedReader br= new BufferedReader(new FileReader("QuizMark.txt"));
while(line=br.readLine()!=null){
s=line.split(",");//your data separated by symbol in file
//First Record with id and marks
int id =Interger.parseInt(s[0]); //conversion from string to int
double marks = Double.parseDouble(s[1]); //conversion from string to double
p[count]= new QuizMark(id,marks);
count++;
}
I have many text files (up to 20) and each file has it's contents like this
21.0|11|1/1/1997
13.3|12|2/1/1997
14.6|9|3/1/1997
and every file has approximately more than 300 lines.
so the problem I'm facing is this, how can I extract all and only the first values
of the file's content.
for example I want to extract the values (21.0,13.3,14.6.....etc) so I can decide the max number and minimum in all of the 20 files.
I have wrote this code from my understanding to experience it on of the files
but it didn't work
String inputFileName = "Date.txt";
File inputFile = new File(inputFileName);
Scanner input = new Scanner(inputFile);
int count = 0;
while (input.hasNext()){
double line = input.nextDouble(); //Error occurs "Exception in thread "main" java.util.InputMismatchException"
count++;
double [] lineArray= new double [365];
lineArray[count]= line;
System.out.println(count);
for (double s : lineArray){
System.out.println(s);
System.out.println(count);
and this one too
String inputFileName = "Date.txt";
File inputFile = new File(inputFileName);
Scanner input = new Scanner(inputFile);
while (input.hasNext()){
String line = input.nextLine();
String [] lineArray = line.split("//|");
for (String s : lineArray){
System.out.println(s+" ");
}
Note: I'm still kind of a beginner in Java
I hope I was clear and thanks
For each line of text, check whether it contains the pipe character. If it does, grab the first portion of the text and parse it to double.
double val = 0.0;
Scanner fScn = new Scanner(new File(“date.txt”));
while(fScn.hasNextLine()){ //Can also use a BufferedReader
data = fScn.nextLine();
if(data.contains("|")) //Ensure line contains "|"
val = Double.parseDouble(data.substring(0, data.indexOf("|"))); //grab value
}
Or you could try some streams, cool stuff
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class MinMaxPrinter {
public static void main(String[] args) {
final List<String> files = Arrays.asList("file", "names", "that", "you", "need");
new MinMaxPrinter().printMinMax(files);
}
public void printMinMax(List<String> fileNames) {
List<Double> numbers = fileNames.stream()
.map(Paths::get)
.flatMap(this::toLines)
.map(line -> line.split("\\|")[0])
.map(Double::parseDouble)
.collect(Collectors.toList());
double max = numbers.stream().max(Double::compare).get();
double min = numbers.stream().min(Double::compare).get();
System.out.println("Min: " + min + " Max: " + max);
}
private Stream<String> toLines(Path path) {
try {
return Files.lines(path);
} catch (IOException e) {
return Stream.empty();
}
}
}
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ((line = br.readLine()) != null) {
String res = s.split("\\|")[0];
}
}
I'm new in Java.
I want to input a text file and create from it a two dimensional array the input is
like this
12,242 323,2324
23,4434 23,4534
23,434 56,3434
....
34,434 43,3443
I have tried
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
public class InputText {
/**
* #param args the command line arguments
* #throws java.io.IOException
*/
public static void main(String[] args) throws IOException {
int i=0;
File file;
file = new File("file.txt");
Scanner read=new Scanner(file);
while (read.hasNextLine()) {
String line=read.nextLine();
System.out.println(line);
}
}
}
which gives me the input but I cannot insert this in an array I tried different ways like splitting it.
Any suggestions?
Sorry for not being clear. The input i mentioned is doubles seperated by spaces. Also the format i gave you is what i get after i run the part of the programm i wrote. What i see in the text file is the numbers seperated by spaces. I tried to implement your suggestion but nothing seemed to work. I'm really lost here....
If you want to split a line to two numbers you can use
string[] numbers = line.split("\\s+");
If you want to read a double with comma
NumberFormat format = NumberFormat.getInstance(Locale.FRANCE);
...
double d1 = format.parse(numbers[0]).doubleValue();
double d2 = format.parse(numbers[1]).doubleValue();
Personally i prefer to use scanner. In that case create it with
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
Scanner scanner2 = new Scanner(scanner.nextLine()).useLocale(Locale.FRANCE);
if (!scanner2.hasNextDouble()){
System.out.println("Do not have a pair");
continue;
}
double d1 = scanner2.nextDouble();
if (!scanner2.hasNextDouble()){
System.out.println("Do not have a pair");
continue;
}
double d2 = scanner2.nextDouble();
//do something
}
After reading the line.. you will have to again split the string on ','. The split string need to be converted into interger. YOu can see as below:
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
public class InputText {
/**
* #param args the command line arguments
* #throws java.io.IOException
*/
public static void main(String[] args) throws IOException {
int i = 0;
File file;
file = new File("file.txt");
Scanner read = new Scanner(file);
while (read.hasNextLine()) {
String line = read.nextLine();
String[] numbers = line.split(",");
for (i = 0; i < numbers.lenght; i++) {
String numStr = numbers[i];
String x=numStr.replaceAll("\\s+",""); //eleminate the space in any.
Double num = Double.valueOf(x);
System.out.println(" num is: " + num); //Here you can store the number in array.
}
}
}
}
Try to use something like that(add also try catch statement)
String line = "";
br = new BufferedReader(new FileReader("file.txt"));
int i=0;
while ((line = br.readLine()) != null) {
// use comma as separator
String[] lineArray= line.split(",");
for(int j=0;j<lineArray.length;j++){
my2DArray[i][j] = lineArray[j];
}
i++;
}
for(int i=0;i<my2DArray[0].length;i++){
for(int j=0;j<my2DArray[1].length;j++){
System.out.print(my2DArray[i][j] + " ");
}
}
Im probably going around this the wrong way, but My question is, how would I go about filling the array for fxRates?
CAD,EUR,GBP,USD
1.0,0.624514066,0.588714763,0.810307
1.601244959,1.0,0.942676548,1.2975
1.698615463,1.060809248,1.0,1.3764
1.234100162,0.772200772,.726532984,1.0
This is the information i have in the CSV file, I was thinking about using the scanner class to read it. Something like
private double[][] fxRates;
String delimiter = ","
Scanner sc = new Scanner(file);
while (sc.hasNextLine()) {
String line = sc.nextLine();
fxRates = line.split(delimiter)
Your way of solving this problem seems OK. But line.split(",") will return a 1D String array. You cannot assign it to fxRates. And also you should know the number of lines or rows in order to initialize fxRates at the beginning. Otherwise you should use a dynamic list structure like ArrayList.
Supposing you have 50 lines in your file, you can use something like:
private String[][] fxRates = String[50][];
String delimiter = ",";
Scanner sc = new Scanner(file);
int index=0;
while (sc.hasNextLine())
{
String line = sc.nextLine();
fxRates[index++] = line.split(delimiter)
}
And note that I've declared fxRates as a 2D String array, if you need double values you should do some conversion in place or later on.
import java.nio.charset.Charset;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.io.IOException;
public class CSVReader{
private String readFile(String path, Charset encoding) throws IOException
{
//Read in all bytes from a file at the specified path into a byte array
//This method will fail if there is no file to read at the specified path
byte[] encoded = Files.readAllBytes(Paths.get(path));
//Convert the array of bytes into a string.
return new String(encoded, encoding);
}
public String readFile(String path)
{
try {
//Read the contents of the file at the specified path into one long String
String content = readFile(path, Charset.defaultCharset());
//Display the string. Feel free to comment this line out.
System.out.println("File contents:\n"+content+"\n\n");
//Return the string to caller
return content;
}catch (IOException e){
//This code will only execute if we could not open a file
//Display the error message
System.out.println("Cannot read file "+path);
System.out.println("Make sure the file exists and the path is correct");
//Exit the program
System.exit(1);
}`enter code here`
return null;
}
}
The result of a split operation is a String array, not an array of double. So one step is missing: converting the Strings to doubles:
private double[][] fxRates = new double[maxLines][4];
String delimiter = ","
int line = 0;
Scanner sc = new Scanner(file);
while (sc.hasNextLine()) {
String line = sc.nextLine();
String[] fxRatesAsString = line.split(delimiter);
for (int i = 0; i < fxRatesAsString.length; i++) {
fxRates[line][i] = Double.parseDouble(fxRatesAsString[i]);
}
Another example;
Double[][] fxRates = new Double[4][];
String delimiter = ",";
//file code goes here
Scanner sc = new Scanner(file);
// Read File Line By Line
int auxI = 0;
// Read File Line By Line
for (int auxI =0; sc.hasNextLine(); auxI++) {
String line = sc.nextLine();
System.out.println(line);
String[] fxRatesAsString = line.split(delimiter);
Double[] fxRatesAsDouble = new Double[fxRatesAsString.length];
for (int i = 0; i < fxRatesAsString.length; i++) {
fxRatesAsDouble[i] = Double.parseDouble(fxRatesAsString[i]);
}
fxRates[auxI] = fxRatesAsDouble;
}
//to double check it
for (int y =0; y<fxRates.length; y++){
for (int x =0; x<fxRates.length; x++){
System.out.print(fxRates[y][x] +" ");
}
System.out.println("");
}
I wouldn't recommend you to parse CSVs in such a way, because Scanner is too low-level and raw solution for this. In comparison, DOM/SAX parsers are better to parse XML rather than regular expressions parsing or whatever that does not consider the document structure. There are CSV parsers that feature good APIs and suggest configuration options during a reader initialization. Just take a look at easy to use CsvReader. Here is a code sample using it:
package q12967756;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import static java.lang.Double.parseDouble;
import static java.lang.System.out;
import com.csvreader.CsvReader;
public final class Main {
private Main() {
}
private static final String MOCK =
"CAD,EUR,GBP,USD\n" +
"1.0,0.624514066,0.588714763,0.810307\n" +
"1.601244959,1.0,0.942676548,1.2975\n" +
"1.698615463,1.060809248,1.0,1.3764\n" +
"1.234100162,0.772200772,.726532984,1.0\n";
private static final char SEPARATOR = ',';
public static void main(String[] args) throws IOException {
// final FileReader contentReader = new FileReader("yourfile.csv");
final StringReader contentReader = new StringReader(MOCK);
final CsvReader csv = new CsvReader(contentReader, SEPARATOR);
csv.readHeaders(); // to skip `CAD,EUR,GBP,USD`
final Collection<double[]> temp = new ArrayList<double[]>();
while ( csv.readRecord() ) {
temp.add(parseRawValues(csv.getValues()));
}
final double[][] array2d = temp.toArray(new double[temp.size()][]);
out.println(array2d[3][1]);
}
private static double[] parseRawValues(String[] rawValues) {
final int length = rawValues.length;
final double[] values = new double[length];
for ( int i = 0; i < length; i++ ) {
values[i] = parseDouble(rawValues[i]);
}
return values;
}
}