I am designing a program that will load a text file into different media file classes (Media > Audio > mp3, Media > Video > Avi, etc).
Now the first line of my text file is how many files there are in total, as in
3
exmaple.mp3,fawg,gseges
test.gif,wfwa,rgeg
ayylmao.avi,awf,gesg
Now that is what is in my text file, I want to first get the first line separately, then loop through the rest of the files.
Now I understand I can simply count how many files are in by using an int that grows as I loop but I want it clear in the file aswell, and I'm not sure how to go about this.
static public Media[] importMedia(String fileName)
{
try {
BufferedReader reader = new BufferedReader(new FileReader(fileName));
String line = reader.readLine();
while(line != null)
{
//Get the first line of the text file seperatly? (Then maybe remove it? idk)
//Split string, create a temp media file and add it to a list for the rest of the lines
}
//String[] split = s.next().split(",");
} catch (Exception ex) { System.out.println(ex.getMessage()); }
return null;
}
I hope my question is clear, if it TL;DR I want to get the first line of a text file separately, then the rest Id like to loop through.
I wouldn't advice using a for-loop here, since the file might contain additional lines (e.g. comments or blank lines) to make it more human-readable. By examining the content of each line, you can make your processing more robust against this sort of thing.
static public Media[] importMedia(String fileName)
{
try {
BufferedReader reader = new BufferedReader(new FileReader(fileName));
// Get and process first line:
String line = reader.readLine(); // <-- Get the first line. You could consider reader as a queue (sort-of), where readLine() dequeues the first element in the reader queue.
int numberOfItems = Integer.valueOf(line); // <-- Create an int of that line.
// Do the rest:
while((line = reader.readLine()) != null) // <-- Each call to reader.readLine() will get the next line in the buffer, so the first time around this will give you the second line, etc. until there are no lines left to read.
{
// You will not get the header here, only the rest.
if(!line.isEmpty() || line.startsWith("#") {
// If the line is not empty and doesn't start with a comment character (I chose # here).
String[] split = line.split(",");
String fileName = split[0];
// etc...
}
}
} catch (Exception ex) { System.out.println(ex.getMessage()); }
return null;
}
You don't need while loop to read up to end of file. Read first line and convert it to int than loop through.
static public Media[] importMedia(String fileName)
{
try {
BufferedReader reader = new BufferedReader(new FileReader(fileName));
// Get and process first line:
int lineNo=Integer.parseInt(reader.readLine());
// Now read upto lineNo
for(int i=0; i < lineNo; i++){
//Do what you need with other lines.
String[] values = reader.readLine().split(",");
}
} catch (Exception e) {
//Your exception handling goes here
}
}
Related
I have a csv file that doesn't always have the same number of lines. However, I want a method to only read me the last line, so I can access the first column of that last line. So far I haven't found a solution, that does exactly that.
Right now I'm just at the point were I would read every single line with BufferedReader and save it into an Array.
public void readPreviousEntryID(){
String path = "csvs/cartEntries.csv";
try {
BufferedReader br = new BufferedReader((new FileReader(path)));
String line;
while ((line = br.readLine() != null)) {
String[] values = line.split(",");
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
Normally I would then access the first entry of every line by using values[0]. But I just want the first value of the last line.
I thought about counting the number of lines in the while loop by incrementing an integer and then using the final value of that integer to access the corresponding line, but I'm not sure if this would work or how I would implement that.
I hope I included enough information to make the problem understandable. This is my first question here and I'm quite new to Java.
Simply read the lines of the file in a loop and save the values of the last line read. After the loop terminates, values contains the contents of the last line in the file.
public void readPreviousEntryID() throws IOException {
String path = "csvs/cartEntries.csv";
try (FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr)) {
String[] values = null;
String line = br.readLine();
while (line != null) {
values = line.split(",");
line = br.readLine();
}
if (values == null) {
throw new IOException("File is empty.");
}
// Handle 'values[0]'
}
}
The advantage of the above code is that you don't need to store the entire file contents in the computer memory. If the CSV file is very large, you may get OutOfMemoryError.
Note that is important to close a file after you have finished reading it. Since Java 7 you can use try-with-resources.
Rather than catch the IOException and wrap it in a RuntimeException, I suggest that you simply declare that method readPreviousEntryID may throw an IOException. Refer to Unchecked Exceptions — The Controversy.
It is probably also a good idea to check, after the loop terminates, that values contains the expected number of elements, e.g.
if (values.length == 5) {
// Handle 'values[0]'
}
else {
throw new IOException("Invalid last line.");
}
Edit
Alternatively, no need to split every line. Just save the last line read and split that last line after the loop terminates.
public void readPreviousEntryID() throws IOException {
String path = "csvs/cartEntries.csv";
try (FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr)) {
String lastLine = null;
String line = br.readLine();
while (line != null) {
lastLine = line;
line = br.readLine();
}
if (lastLine == null) {
throw new IOException("File is empty.");
}
String[] values = lastLine.split(",");
// Handle 'values[0]'
}
}
Why not stored all lines into List and get last line details such as follows
private List<String[]> readLines = new ArrayList<>();
public void readPreviousEntryID(){
String path = "csvs/cartEntries.csv";
try {
String line;
BufferedReader br = new BufferedReader(new FileReader(path));
while ((line = br.readLine()) != null) {
String[] values = line.split(",");
readLines.add(values);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public String[] getLastLine() {
return readLines.get(readLines.size()-1);
}
This above function will gives the last row of csv file.
In Linux one would use the tail command to print the n last lines. Search java tail will get you some implementations.
A good fast implementation for large files would use a RandomAccessFile, maybe a MemoryMappedByteBuffer, and search back from the end for a \n.
In your case you can keep it simple.
public String readPreviousEntryID(){
Path path = Paths.get("csvs/cartEntries.csv");
try (Stream<String> lines = Files.lines(path, Charset.defaultCharset())) {
return lines
.filter(line -> !line.isEmpty())
.reduce("", (acc, line) -> line);
} catch (FileNotFoundException e) {
// You gave a relative path, show the actual full path:
System.out.println("File not found: " + Files.toAbsolutePath());
throw new RuntimeException(e);
} // Automatically closes the Stream lines, even on exception or return.
}
Try-with-resources try (... declarations of AutoCloseables ...) { ... } ensuring the call to .close().
Stream, the newest walk through items. Here skipping empty lines and "accumulating" just the last line. You need not keep all lines in memory.
Lambdas, x -> ... or (x, y) -> ... declare an anonymous function with 1 resp. 2 parameter declarations.
Path is a generalisation of disk file only File. Path can also be from an URL, inside a zip file etcetera.
Files is a worthwile utility class providing many Path related goodies. Files.
Some good Answers have been posted. Here is a variation using streams.
Also, learn about NIO.2 as the modern way to work with files in Java.
Some untested code to try:
Path path = Paths.get( "/csvs" , "cartEntries.csv" ) ;
Optional < String > lastLine =
Files
.lines( path )
.reduce( ( previousLine , currentLine ) -> currentLine ) ;
if( lastLine.isPresent() ) {
String[] parts = lastLine.get().split( "," ) ;
…
}
Or, re-organized into a one-liner:
String[] parts =
Files
.lines(
Paths.get( "/csvs" , "cartEntries.csv" )
)
.reduce(
( previousLine , currentLine ) -> currentLine
)
.map(
line -> line.split.( "," )
)
.orElse(
String[] :: new
)
;
I am new to Android Development and Java. Please bear with me.
So, I am making an application which opens a random webpage from a list of webpage
The code reads a text file present in the assets folder which contains all the links, and makes a list of the links and then selects one at random.
So the problem is that I have put in log messages, to check if the program is reading and populating the array till the last line of the text.
The log messages show the size of the list as 1301. Whereas my text file contains 2601 links.
I can't to seem to understand where am I going wrong.
Here is the java code snippet,
int sd=0;
List<String> links=new ArrayList<>();
try {
AssetManager assetManager = getAssets();
InputStream assetIn = assetManager.open("android");
BufferedReader r = new BufferedReader(new InputStreamReader(assetIn));
while (r.readLine() != null) {
links.add(r.readLine());
sd++;
}
} catch (IOException e) {
e.printStackTrace();
}
Random r=new Random();
//String len= Integer.toString(links.size());
String len= Integer.toString(sd);
Log.i("total loop",len);
String randomLink=links.get(r.nextInt(links.size()));
Log.i("link select :",randomLink);
webView.loadUrl(randomLink);
You read line on loop twicely, here:
1) while (r.readLine() != null) {
2) links.add(r.readLine());
So it should be:
String line = "";
while ((line = r.readLine()) != null) {
links.add(line);
sd++;
}
You are calling readLine() twice, thus reading 2 lines instead of 1 on each iteration:
while (r.readLine() != null) { // reads a line
links.add(r.readLine()); // reads another line
sd++; // increments by 1 every *2* lines read
}
You probably wanted to use:
while ((line = r.readLine()) != null) {
links.add(line);
sd++;
}
I have to make an EPG app using java, but I am kind of new in programming and it's due tomorrow and it's still not working properly.
I have a question about a small part: I have to read the programs from a text file. Each line contains multiple things, the channel, the title of the program, a subtitle, a category, etcetera.
I have to make sure that I can read the separate parts of each line, but it's not really working, it's only printing the parts from the first line.
I am trying, but I can't find why it's not printing all the parts from all the lines in stead of printing only the parts from the first line. Here's the code:
BufferedReader reader = new BufferedReader(newFileReader(filepath));
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
}
String[] parts = line.split("\\|", -1);
for(int i = 0; i < parts.length; i++) {
System.out.println(parts[i]);
}
reader.close();
Does anybody know how to get all the lines in stead of only the first?
Thank you!
readLine() only reads one line, so you need to loop it, as you said.
BUT with reading to the String inside of the while loop you always overwrite that String.
You would need to declare the String above the while loop that you can access it from outside, too.
BTW, it seems that your braces for the if don't match.
Anyway, I'd fill the information into an ArrayList, look below:
List<String> list = new ArrayList<>();
String content;
// readLine() and close() may throw errors, so they require you to catch it…
try {
while ((content = reader.readLine()) != null) {
list.add(content);
}
reader.close();
} catch (IOException e) {
// This just prints the error log to the console if something goes wrong
e.printStackTrace();
}
// Now proceed with your list, e.g. retrieve first item and split
String[] parts = list.get(0).split("\\|", -1);
// You can simplify the for loop like this,
// you call this for each:
for (String s : parts) {
System.out.println(s);
}
Use apache commons lib
File file = new File("test.txt");
List<String> lines = FileUtils.readLines(file);
As ArrayList is Dynamic,try,
private static List<String> readFile(String filepath) {
String line = null;
List<String> list = new ArrayList<String>();
try {
BufferedReader reader = new BufferedReader(new FileReader(filepath));
while((line = reader.readLine()) != null){
list.add(line);
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
I have a problem in java and i dont understand why, since i think i am doing text-book stuff.
An overview in what of want to do is:
I want to create a file that contains in each line two strings: documentPath, documentID (in this format: "documentPath;documentID;")
I want to be able to add lines at the end of the file and load the file to a Java Data Structure, lets say a HashSet.
Each time i want to add a new line, i load all the file in a HashSet, check if the line i want to add is not already there and eventually add it at the end. (small number of data - don't care about efficiency)
The code
Add file:
public void addFile(String documentPath) {
this.loadCollection(); //METHOD IS NOT CONTINUING: ERROR HERE
if (!documentsInfo.contains(documentPath)) {
try {
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(this.collectionFile, true)));
DocumentInfo documentInfo = new DocumentInfo(documentPath, ++this.IDcounter);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Load file:
public void loadCollection() {
if (loaded) {return;}
BufferedReader br;
try {
br = new BufferedReader(new FileReader(collectionFile));
String line;
while ( (line = br.readLine())!= null ) { //PROBLEM HERE
System.out.println("the line readed from file-" + line + "-");
System.out.println("is the line null: "+ (line==null));
System.out.println("line length: " + line.length());
DocumentInfo documentInfo = new DocumentInfo(line);
documentsInfo.add(documentInfo);
}
br.close();
open = true;
} catch (IOException e) {
e.printStackTrace();
}
}
create the line to add:
public DocumentInfo(String fileLine) {
String delimiter = Repository.DOCUMENT_FILE_SEPARATOR;
StringTokenizer tok = new StringTokenizer(fileLine, delimiter);
System.out.println("Tokenizer starts with string: " + fileLine);
this.documentPath = tok.nextToken(); //EXCEPTION here
this.documentId = Integer.parseInt(tok.nextToken());
}
public String toString() {
String sep = Repository.DOCUMENT_FILE_SEPARATOR;
return this.getDocumentPath()+sep+this.getDocumentId()+sep+"\n";
}
I am getting the exception at the Tokenizer method (java.util.NoSuchElementException) when i try to get the nextToken, but the problem comes from the loadCollection() method. The first time i read the contents of the file nothing is there, the line is empty (lenght: 0) but the line is not null, so the while-condition fails to stop the while iteration.
Here is what i get from the debbuging prints:
the line readed from file--
is the line null: false
line length: 0
Tokenizer starts with string:
Can anyone help me with this?
You get a null only when you have exhausted the stream. But the first line of the stream (your file) is just an empty line - and you load it, the result of the empty line, is an empty string (""). It can be easily solved by skipping lines with string.length() == 0, by adding the following in your while loop:
if (line.length() == 0) continue;
You might want to consider using trim() before checking the length as well, to avoid nasty spaces making the string.length() > 0
I need to have this file print to an array, not to screen.And yes, I MUST use an array - School Project - I'm very new to java so any help is appreciated. Any ideas? thanks
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
public class HangmanProject
{
public static void main(String[] args) throws FileNotFoundException
{
String scoreKeeper; // to keep track of score
int guessesLeft; // to keep track of guesses remaining
String wordList[]; // array to store words
Scanner keyboard = new Scanner(System.in); // to read user's input
System.out.println("Welcome to Hangman Project!");
// Create a scanner to read the secret words file
Scanner wordScan = null;
try {
wordScan = new Scanner(new BufferedReader(new FileReader("words.txt")));
while (wordScan.hasNext()) {
System.out.println(wordScan.next());
}
} finally {
if (wordScan != null) {
wordScan.close();
}
}
}
}
Nick, you just gave us the final piece of the puzzle. If you know the number of lines you will be reading, you can simply define an array of that length before you read the file
Something like...
String[] wordArray = new String[10];
int index = 0;
String word = null; // word to be read from file...
// Use buffered reader to read each line...
wordArray[index] = word;
index++;
Now that example's not going to mean much to be honest, so I did these two examples
The first one uses the concept suggested by Alex, which allows you to read an unknown number of lines from the file.
The only trip up is if the lines are separated by more the one line feed (ie there is a extra line between words)
public static void readUnknownWords() {
// Reference to the words file
File words = new File("Words.txt");
// Use a StringBuilder to buffer the content as it's read from the file
StringBuilder sb = new StringBuilder(128);
BufferedReader reader = null;
try {
// Create the reader. A File reader would be just as fine in this
// example, but hay ;)
reader = new BufferedReader(new FileReader(words));
// The read buffer to use to read data into
char[] buffer = new char[1024];
int bytesRead = -1;
// Read the file to we get to the end
while ((bytesRead = reader.read(buffer)) != -1) {
// Append the results to the string builder
sb.append(buffer, 0, bytesRead);
}
// Split the string builder into individal words by the line break
String[] wordArray = sb.toString().split("\n");
System.out.println("Read " + wordArray.length + " words");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (Exception e) {
}
}
}
The second demonstrates how to read the words into an array of known length. This is probably closer to the what you actually want
public static void readKnownWords()
// This is just the same as the previous example, except we
// know in advance the number of lines we will be reading
File words = new File("Words.txt");
BufferedReader reader = null;
try {
// Create the word array of a known quantity
// The quantity value could be defined as a constant
// ie public static final int WORD_COUNT = 10;
String[] wordArray = new String[10];
reader = new BufferedReader(new FileReader(words));
// Instead of reading to a char buffer, we are
// going to take the easy route and read each line
// straight into a String
String text = null;
// The current array index
int index = 0;
// Read the file till we reach the end
// ps- my file had lots more words, so I put a limit
// in the loop to prevent index out of bounds exceptions
while ((text = reader.readLine()) != null && index < 10) {
wordArray[index] = text;
index++;
}
System.out.println("Read " + wordArray.length + " words");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (Exception e) {
}
}
}
If you find either of these useful, I would appropriate it you would give me a small up-vote and check Alex's answer as correct, as it's his idea that I've adapted.
Now, if you're really paranoid about which line break to use, you can find the values used by the system via the System.getProperties().getProperty("line.separator") value.
Do you need more help with the reading the file, or getting the String to a parsed array? If you can read the file into a String, simply do:
String[] words = readString.split("\n");
That will split the string at each line break, so assuming this is your text file:
Word1
Word2
Word3
words will be: {word1, word2, word3}
If the words you are reading are stored in each line of the file, you can use the hasNextLine() and nextLine() to read the text one line at a time. Using the next() will also work, since you just need to throw one word in the array, but nextLine() is usually always preferred.
As for only using an array, you have two options:
You either declare a large array, the size of whom you are sure will never be less than the total amount of words;
You go through the file twice, the first time you read the amount of elements, then you initialize the array depending on that value and then, go through it a second time while adding the string as you go by.
It is usually recommended to use a dynamic collection such as an ArrayList(). You can then use the toArray() method to turnt he list into an array.