I want to make something read from inputstream to store in an int[] when I type "read 1 2 3 4". what should i do?
I do not know the size of the array, everything is dynamic...
Here is the current code:
BufferedReader stdin = new BufferedReader(
new InputStreamReader(System.in));
String line = stdin.readLine();
StringTokenizer st = new StringTokenizer(line);
String command = st.nextToken();
if (command.equals("read")) {
while (st.nextToken() != null) {
//my problem is no sure the array size
}
}
You need to build something to parse the input stream. Assuming it's literally as uncomplex as you've indicated the first thing you need to do is get the line out of the InputStream, you can do that like this:
// InputStream in = ...;
// read and accrue characters until the linebreak
StringBuilder sb = new StringBuilder();
int c;
while((c = in.read()) != -1 && c != '\n'){
sb.append(c);
}
String line = sb.toString();
Or you can use a BufferedReader (as suggested by comments):
BufferedReader rdr = new BufferedReader(new InputStreamReader(in));
String line = rdr.readLine();
Once you have a line to process you need to split it into pieces, then process the pieces into the desired array:
// now process the whole input
String[] parts = line.split("\\s");
// only if the direction is to read the input
if("read".equals(parts[0])){
// create an array to hold the ints
// note that we dynamically size the array based on the
// the length of `parts`, which contains an array of the form
// ["read", "1", "2", "3", ...], so it has size 1 more than required
// to hold the integers, thus, we create a new array of
// same size as `parts`, less 1.
int[] inputInts = new int[parts.length-1];
// iterate through the string pieces we have
for(int i = 1; i < parts.length; i++){
// and convert them to integers.
inputInts[i-1] = Integer.parseInt(parts[i]);
}
}
I'm sure some of these methods can throw exceptions (at least read and parseInt do), I'll leave handling those as an exercise.
You either use a storing structure with nodes, that you can easily append one after another, or, if you really must use arrays, you need to allocate space periodically, as it becomes necessary.
Parse-out the data and keyword from your string then push it into something like this:
public static Integer[] StringToIntVec( String aValue )
{
ArrayList<Integer> aTransit = new ArrayList<Integer>();
for ( String aString : aValue.split( "\\ ") )
{
aTransit.add( Integer.parseInt( aString ) );
}
return aTransit.toArray( new Integer[ 0 ] );
}
Related
I'm pretty new to Java (currently enrolled in my first programming class), so the answer to my question could be right in front of me.
My goal is to read in a text file that reads as follows:
4563123,112211324135412
2312311,222121324135211
2312345,112211324135421
5527687,212111313124412
7867567,111111111111111
where the first set of numbers is an ID, and the second set is a set of answers to a test (of which I have the key). Once I've read in the answers I need to store them in an array (and I assume just an array, as my class has not covered ArrayLists yet). All of this data would need to be stored in one array, since I need to return it at the end of the method.
Here is the code that I have so far:
public static String[] readFile(String filename)throws IOException{
Scanner inFile = new Scanner(filename);
String line;
String[] results = new String[101];
int i = 0;
while (inFile.hasNextLine()){
line = inFile.nextLine();
String[] incoming = line.split(",");
String wid = incoming[0];
String answer = incoming[1];
results[i] = wid;
results[i + 1] = answer;
i += 2;
}
inFile.close();
return results;
}
It's safe to ignore the String filename, it was passed in from the main.
Every time I run this method, I keep running into an ArrayOutOfBoundsException, mainly when I try to assign incoming[1] to answer.
I've been staring at this code longer than what is probably good for me, but it seems that I just can't wrap my head around it. Any help would be appreciated, whether that be telling me what is wrong or what I can do to improve.
Since you are using Java 7, use the new Files API and a try-with-resources statement; also, avoid copying empty lines:
final Path file = Paths.get(filename);
String line;
String[] incoming;
String[] results = new String[101];
int nrElements = 0;
try (
final BufferedReader reader = Files.newBufferedReader(path,
StandardCharsets.UTF_8);
) {
while ((line = reader.readLine()) != null) {
incoming = line.split(",");
if (incoming.length != 2)
continue;
results[nrElements++] = incoming[0];
results[nrElements++] = incoming[1];
}
}
return Arrays.copyOfRange(results, 0, nrElements);
Either you are having an empty line in your file. Or a garbage line that doesn't have any comma in it. So before accessing the slitted array, just give a check.
if(incoming != null && incoming.length >= 2){
String wid = incoming[0];
String answer = incoming[1];
// ... other dependent codes go here!
}
It will help you to avoid the Exception.
I have a text file with 300 lines or so. And the format is like:
Name Amount Unit CountOfOrder
A 1 ml 5000
B 1 mgm 4500
C 4 gm 4200
// more data
I need to read the text file line by line because each line of data should be together for further processing.
Now I just use string array for each line and access the data by index.
for each line in file:
array[0] = {data from the 'Name' column}
array[1] = {data from the 'Amount' column}
array[2] = {data from the 'Unit' column}
array[3] = {data from the 'CountOfOrder' column}
....
someOtherMethods(array);
....
However, I realized that if the text file changes its format (e.g. switch two columns, or insert another column), it would break my program (accessing through index might be wrong or even cause exception).
So I would like to use the title as reference to access each column. Maybe HashMap is a good option, but since I have to keep each line of data together, if I build a HashMap for each line, that would be too expensive.
Does anyone have any thought on this? Please help!
you only need a single hash map to map your column names to the proper column index. you fill the arrays by indexing with integers as you did before, to retrieve a column by name you'd use array[hashmap.get("Amount")].
You can read the file using opencsv.
CSVReader reader = new CSVReader(new FileReader("yourfile.txt"), '\t');
List<String[]> lines = reader.readAll();
The fist line contains the headers.
you can read each line of the file and assuming that the first line of the file has the column header you can parse that line to get all the names of the columns.
String[] column_headers = firstline.split("\t");
This will give you the name of all the columns now you just read through splitting on tabs and they will all line up.
You could do something like this:
BufferedReader in = new BufferedReader(new InputStreamReader(
new FileInputStream(FILE)));
String line = null;
String[] headers = null;
String[] data = null;
Map<String, List<String>> contents = new HashMap<String, List<String>>();
if ((line = in.readLine()) != null) {
headers = line.split("\t");
}
for(String h : headers){
contents.put(h, new ArrayList<String>());
}
while ((line = in.readLine()) != null) {
data = line.split("\t");
if(data.length != headers.length){
throw new Exception();
}
for(int i = 0; i < data.length; i++){
contents.get(headers[i]).add(data[i]);
}
}
It would give you flexibility, and would only require making the map once. You can then get the data lists from the map, so it should be a convenient data structure for the rest of your program to use.
This will give you individual list of columns.
public static void main(String args[]) throws FileNotFoundException, IOException {
List<String> headerList = new ArrayList<String>();
List<String> column1 = new ArrayList<String>();
List<String> column2 = new ArrayList<String>();
List<String> column3 = new ArrayList<String>();
List<String> column4 = new ArrayList<String>();
int lineCount=0;
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
String tokens[];
while (line != null) {
tokens = line.split("\t");
if(lineCount != 0)
{
int count = 0;
column1.add(tokens[count]); ++count;
column2.add(tokens[count]); ++count;
column3.add(tokens[count]); ++count;
column4.add(tokens[count]); ++count;
continue;
}
if(lineCount==0){
for(int count=0; count<tokens.length; count++){
headerList.add(tokens[count]);
lineCount++;
}
}
}
} catch (IOException e) {
} finally {
br.close();
}
}
using standard java.util.Scanner
String aa = " asd 9 1 3 \n d -1 4 2";
Scanner ss = new Scanner(aa);
ss.useDelimiter("\n");
while ( ss.hasNext()){
String line = ss.next();
Scanner fs = new Scanner(line);
System.out.println( "1>"+ fs.next()+" " +fs.nextInt() +" " +fs.nextLong()+" " +fs.nextBigDecimal());
}
using a bunch of hashmap's is ok...i won't be afraid ;)
if you need to process a lot of data...then try to translate your problem into a dataprocessing transformation
for example:
read all of you data into a hashmap's, but store them in a database using some JPA implementation....then you can go round'a'round your data ;)\
So basically I'm reading a text file that has a bunch of lines. I need to extract certain lines from the text file and add those specific lines into string array. I've been trying to split each newLine with: "\n" , "\r". This did not work. I keep getting this error as well:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at A19010.main(A19010.java:47)
Here is the code:
Path objPath = Paths.get("dirsize.txt");
if (Files.exists(objPath)){
File objFile = objPath.toFile();
try(BufferedReader in = new BufferedReader(
new FileReader(objFile))){
String line = in.readLine();
while(line != null){
String[] linesFile = line.split("\n");
String line0 = linesFile[0];
String line1 = linesFile[1];
String line2 = linesFile[2];
System.out.println(line0 + "" + line1);
line = in.readLine();
}
}
catch(IOException e){
System.out.println(e);
}
}
else
{
System.out.println(
objPath.toAbsolutePath() + " doesn't exist");
}
String[] linesFile = new String[] {line}; // this array is initialized with a single element
String line0 = linesFile[0]; // fine
String line1 = linesFile[1]; // not fine, the array has size 1, so no element at second index
String line2 = linesFile[2];
You're creating a String[] linesFile with one element, line, but then trying to access elements at index 1 and 2. This will give you an ArrayIndexOutOfBoundsException
You're not actually splitting anything here. in.readLine();, as the method says, reads a full line from the file.
Edit: You can add lines (Strings) dynamically to a list instead of an array, since you don't know the size.
List<String> lines = new LinkedList<String>(); // create a new list
String line = in.readLine(); // read a line at a time
while(line != null){ // loop till you have no more lines
lines.add(line) // add the line to your list
line = in.readLine(); // try to read another line
}
readLine() method reads a entire line from the input but removes the newLine characters from it. When you split the line on \n character, you will not find one in the String. Hence, you get the exception.
Please, refer the answer in this link for more clarity.
You are initializing your String array with 1 element, namely line. linesFile[0] is therefore line and the rest of your array is out of bounds.
Try this:
String[] linesFile = line.split("SPLIT-CHAR-HERE");
if(linesFile.length >= 3)
{
String line0 = linesFile[0];
String line1 = linesFile[1];
String line2 = linesFile[2];
// further logic here
}else
{
//handle invalid lines here
}
You are using array to store the strings. Instead use ArrayList from Java as ArrayList are dynamically growing. after your reading operation completes convert it into array.
String line = in.readLine();
ArrayList<String> str_list = new ArrayList<String>();
String[] strArr = new String[str_list.size()];
while(line != null){
str_list.add(line);
line = in.readLine();
}
// at the end of the operation convert Arraylist to array
return str_list.toArray(strArr);
The issue here is that you are creating a new String array every time your parser reads in a new line. You then populate only the very first element in that String array with the line that is being read in with:
String[] linesFile = new String[] {line};
Since you create a new String[] with one element every single time your while loop runs from the top, you lose the values it stored from the previous iteration.
The solution is to use new String[]; right before you enter the while loop. If you don't know how to use ArrayList, then I suggest a while loop like this:
int numberOfLine = 0;
while (in.readLine() != null)
{
numberOfLine++;
}
String linesFile = new String[numberOfLine];
This will let you avoid using a dynamically resized ArrayList because you know how many lines your file contains from the above while loop. Then you would keep an additional counter (or resuse numberOfLine since we have no use for it anymore) so that you can populate this array:
numberOfLine = 0;
in = new BufferedReader(new FileReader(objFile)); // reset the buffer
while ((String line = in.readLine()) != null)
{
linesFile[numberOfLine] = line;
numberOfLine++;
}
At this point linesFile should be correctly populated with the lines in your file, such that linesFile[i] can be used to access the i'th line in the file.
I can successfully read text file using InputFileStream and Scanner classes. It's very easy but I need to do something more complex than that. A little background about my project first.. I have a device with sensors, and I'm using logger that will log every 10sec data from sensors to a text file. Every 10 sec its a new line of data. So what I want is when I read a file is to grab each separate sensor data into an array. For example:
velocity altitude latitude longitude
22 250 46.123245 122.539283
25 252 46.123422 122.534223
So I need to grab altitude data (250, 252) into an array alt[]; and so forth vel[], lat[], long[]...
Then the last line of the text file will different info, just a single line. It will have the date, distance travelled, timeElapsed..
So after doing a little research I came across InputStream, Reader, StreamTokenizer and Scanner class. My question is which one would you recommend for my case? Is it possible to do what I need to do in my case? and will it be able to check what the last line of the file is so it can grab the date, distance and etc.. Thank you!
Reader + String.split()
String line;
String[] values;
BufferedReader reader = new BufferedReader(new FileReader(args[0]));
List<Integer> velocity = new ArrayList<Integer>();
List<Integer> altitude = new ArrayList<Integer>();
List<Float> latitude = new ArrayList<Float>();
List<Float> longitude = new ArrayList<Float>();
while (null != (line = reader.readLine())) {
values = line.split(" ");
if (4 == values.length) {
velocity.add(Integer.parseInt(values[0]));
altitude.add(Integer.parseInt(values[1]));
latitude.add(Float.parseFloat(values[2]));
longitude.add(Float.parseFloat(values[3]));
} else {
break;
}
}
If you need arrays not list:
velocity.toArray();
As far I undestand data lines has 4 items and last line has 3 items (date, distance, elapsed time)
I would use Scanner. Take a look at the examples here. Another option for you to use BufferedReader to read a line and then have parse method to parse that line into the tokens you want.
Also you might find this thread to be useful.
Very quick code base on the link above. The inputs array has your file data tokens.
public static void main(String[] args) {
BufferedReader in=null;
List<Integer> velocityList = new ArrayList<Integer>();
List<Integer> altitudeList = new ArrayList<Integer>();
List<Double> latitudeList = new ArrayList<Double>();
List<Double> longitudeList = new ArrayList<Double>();
try {
File file = new File("D:\\test.txt");
FileReader reader = new FileReader(file);
in = new BufferedReader(reader);
String string;
String [] inputs;
while ((string = in.readLine()) != null) {
inputs = string.split("\\s");
//here is where we copy the data from the file to the data stucture
if(inputs!=null && inputs.length==4){
velocityList.add(Integer.parseInt(inputs[0]));
altitudeList.add(Integer.parseInt(inputs[1]));
latitudeList.add(Double.parseDouble(inputs[2]));
longitudeList.add(Double.parseDouble(inputs[3]));
}
}
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
if(in!=null){
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//here are the arrays you want!!!
Integer [] velocities = (Integer[]) velocityList.toArray();
Integer [] altitiudes = (Integer[]) altitudeList.toArray();
Double [] longitudes = (Double[]) longitudeList.toArray();
Double [] latitudes = (Double[]) latitudeList.toArray();
}
As your data is relatively simple, BufferedReader and StringTokenizer should do the trick. You'll have to read ahead by one line to detect when there are no more lines left.
Your code could be something like this
BufferedReader reader = new BufferedReader( new FileReader( "your text file" ) );
String line = null;
String previousLine = null;
while ( ( line = reader.readLine() ) != null ) {
if ( previousLine != null ) {
//tokenize and store elements of previousLine
}
previousLine = line;
}
// last line read will be in previousLine at this point so you can process it separately
But how you process the line itself is really up to you, you can use Scanner if you're feeling more comfortable with it.
I have a multidimensional array built from Strings that is initially created with the size [50][50], this is too big and now the array is full of null values, I am currently trying to remove these said null values, I have managed to resize the array to [requiredSize][50] but cannot shrink it any further, could anyone help me with this? I have scoured the internet for such an answer but cannot find it.
Here is my complete code too (I realise there may be some very unclean parts in my code, I am yet to clean anything up)
import java.io.*;
import java.util.*;
public class FooBar
{
public static String[][] loadCSV()
{
FileInputStream inStream;
InputStreamReader inFile;
BufferedReader br;
String line;
int lineNum, tokNum, ii, jj;
String [][] CSV, TempArray, TempArray2;
lineNum = tokNum = ii = jj = 0;
TempArray = new String[50][50];
try
{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Please enter the file path of the CSV");
String fileName = in.readLine();
inStream = new FileInputStream(fileName);
inFile = new InputStreamReader(inStream);
br = new BufferedReader(inFile);
StringTokenizer tok,tok2;
lineNum = 0;
line = br.readLine();
tokNum = 0;
tok = new StringTokenizer(line, ",");
while( tok.hasMoreTokens())
{
TempArray[tokNum][0] = tok.nextToken();
tokNum++;
}
tokNum = 0;
lineNum++;
while( line != null)
{
line = br.readLine();
if (line != null)
{
tokNum = 0;
tok2 = new StringTokenizer(line, ",");
while(tok2.hasMoreTokens())
{
TempArray[tokNum][lineNum] = tok2.nextToken();
tokNum++;
}
}
lineNum++;
}
}
catch(IOException e)
{
System.out.println("Error file may not be accessible, check the path and try again");
}
CSV = new String[tokNum][50];
for (ii=0; ii<tokNum-1 ;ii++)
{
System.arraycopy(TempArray[ii],0,CSV[ii],0,TempArray[ii].length);
}
return CSV;
}
public static void main (String args[])
{
String [][] CSV;
CSV = loadCSV();
System.out.println(Arrays.deepToString(CSV));
}
}
The CSV file looks as follows
Height,Weight,Age,TER,Salary
163.9,46.8,37,72.6,53010.68
191.3,91.4,32,92.2,66068.51
166.5,51.1,27,77.6,42724.34
156.3,55.7,21,81.1,50531.91
It can take any size obviously but this is just a sample file.
I just need to resize the array so that it will not contain any null values.
I also understand a list would be a better option here but it is not possible due to outside constraints. It can only be an multi dimensional array.
I think you need 3 changes to your program
After your while loop lineNum will be 1 more than the number of lines in the file so instead of declaring CSV to String[tokNum][50] declare it as CSV = new String[tokNum][lineNum-1];
tokNum will be the number of fields in a row so your for loop condition should be ii<tokNum rather than ii<tokNum-1
The last parameter for your arraycopy should be lineNum-1
i.e. the modified code to build your CSV array is:
CSV = new String[tokNum][lineNum-1];
for (ii=0; ii<tokNum ;ii++)
{
System.arraycopy(TempArray[ii],0,CSV[ii],0,lineNum-1);
}
and the output will then be:
[[Height, 163.9, 191.3, 166.5, 156.3], [Weight, 46.8, 91.4, 51.1, 55.7],
[Age, 37, 32, 27, 21], [TER, 72.6, 92.2, 77.6, 81.1],
[Salary, 53010.68, 66068.51, 42724.34, 50531.91]]
Notice that you don't really need to handle the first line of the file separately from the others but that is something you can cover as part of your cleanup.
10 to 1 this is a homework assignment. However, it looks like you've put somethought into it.
Don't make the TempArray variable. Make a "List of List of Strings". Something like:
List<List<String>> rows = new ArrayList<ArrayList<String>>();
while(file.hasMoreRows()) { //not valid syntax...but you get the jist
String rowIText = file.nextRow(); //not valid syntax...but you get the jist
List<String> rowI = new ArrayList<String>();
//parse rowIText to build rowI --> this is your homework
rows.add(rowI);
}
//now build String[][] using fully constructed rows variable
Here's an observation and a suggestion.
Observation: Working with (multidimensional) arrays is difficult in Java.
Suggestion: Don't use arrays to represent complex data types in Java.
Create classes for your data. Create a List of people:
class Person {
String height; //should eventually be changed to a double probably
String weight; // "
//...
public Person( String height, String weight /*, ... */ ) {
this.height = height;
this.weight = weight;
//...
}
}
List<Person> people = new ArrayList<Person>();
String line;
while ( (line = reader.nextLine()) != null ) {
String[] records = line.split(",");
people.add(new Person (records[0], records[1] /*, ... */));
}